在Spring Boot中,你可以通过以下几种方式来校验上传的文件是否为Excel文件:
方案一:基于文件扩展名和Content-Type校验
java
@PostMapping("/uploadAndParseExcelFile")
@Debounce(key = "uploadAndParseExcelFile", value = 10000)
public Result>> uploadAndParseExcelFile(@RequestParam("uploadFile") MultipartFile uploadFile) {
log.info("【上传Excel文件】,解析Excel文件,/uploadAndParseExcelFile,uploadFile = {}", uploadFile);
// 校验文件是否为空
if (uploadFile.isEmpty()) {
return Result.error("请选择要上传的文件");
}
// 校验文件类型
if (!isExcelFile(uploadFile)) {
return Result.error("请上传有效的Excel文件(.xls 或 .xlsx 格式)");
}
List
方案二:使用注解校验(推荐)
首先创建自定义校验注解:
java
/**
* Excel文件校验注解
*/
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ExcelFileValidator.class)
public @interface ValidExcelFile {
String message() default "请上传有效的Excel文件(.xls 或 .xlsx 格式)";
Class[] groups() default {};
Class[] payload() default {};
}
创建校验器:
java
/**
* Excel文件校验器
*/
public class ExcelFileValidator implements ConstraintValidator {
private static final List EXCEL_EXTENSIONS = Arrays.asList("xls", "xlsx");
private static final List EXCEL_CONTENT_TYPES = Arrays.asList(
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
);
@Override
public boolean isValid(MultipartFile file, ConstraintValidatorContext context) {
if (file == null || file.isEmpty()) {
return false;
}
// 校验文件名
String originalFilename = file.getOriginalFilename();
if (originalFilename == null) {
return false;
}
// 校验扩展名
String extension = getFileExtension(originalFilename).toLowerCase();
if (!EXCEL_EXTENSIONS.contains(extension)) {
return false;
}
// 校验Content-Type
String contentType = file.getContentType();
if (contentType != null && !EXCEL_CONTENT_TYPES.contains(contentType)) {
return false;
}
return true;
}
private String getFileExtension(String filename) {
int lastDotIndex = filename.lastIndexOf(".");
return lastDotIndex == -1 ? "" : filename.substring(lastDotIndex + 1);
}
}
然后在Controller中使用:
java
@PostMapping("/uploadAndParseExcelFile")
@Debounce(key = "uploadAndParseExcelFile", value = 10000)
public Result>> uploadAndParseExcelFile(
@ValidExcelFile @RequestParam("uploadFile") MultipartFile uploadFile) {
log.info("【上传Excel文件】,解析Excel文件,/uploadAndParseExcelFile,uploadFile = {}", uploadFile);
List
方案三:使用全局异常处理
创建全局异常处理器:
java
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ConstraintViolationException.class)
@ResponseBody
public Result handleConstraintViolationException(ConstraintViolationException e) {
return Result.error(e.getMessage());
}
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseBody
public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
String errorMessage = e.getBindingResult().getFieldErrors().stream()
.map(FieldError::getDefaultMessage)
.collect(Collectors.joining(", "));
return Result.error(errorMessage);
}
}
方案四:在Service层进行校验
你也可以在Service层进行更严格的校验:
java
@Service
public class FileUploadService {
public List
推荐使用方案
推荐使用方案二(注解校验),因为:
代码更清晰,职责分离
可复用性强
与Spring的校验框架集成良好
易于维护和扩展
选择哪种方案取决于你的具体需求和项目架构。如果只是简单的校验,方案一就足够了;如果需要更好的代码结构和可复用性,建议使用方案二。
实例代码:
1、使用注解 @ValidExcelFile 校验是否Excel文件
src/main/java/com/weiyu/controller/FileUploadController.java
/** * 上传解析Excel文件,返回解析后的列表数据 *
* 因为前端是用 "Content-Type": "multipart/form-data" 的方式发送的请求,这里就不能用 @RequestBody,而是用 MultipartFile * 并且形参名称 uploadFile 需要与前端定义的保持一致 * * @param uploadFile 上传需要解析的Excel文件,结构见 {@link MultipartFile} * @return 列表数据 {@link Result}<{@link List}<{@link Map}<{@link String},{@link Object}>>> * @apiNote 本接口使用防抖机制,默认 10s 内重复请求会被忽略 */ @PostMapping("/uploadAndParseExcelFile") @Debounce(key = "uploadAndParseExcelFile", value = 10000) // @ResponseBody // 直接序列化返回值,使用 Result>> 替换 ResponseEntity public Result
>> uploadAndParseExcelFile(@ValidExcelFile MultipartFile uploadFile) { log.info("【上传Excel文件】,解析Excel文件,/uploadAndParseExcelFile,uploadFile = {}", uploadFile); List
2、新建注解 @ValidExcelFile
src/main/java/com/weiyu/annotation/ValidExcelFile.java
package com.weiyu.annotation;
import com.weiyu.validation.ExcelFileValidator;
import jakarta.validation.Constraint;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Excel文件校验注解
*/
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ExcelFileValidator.class)
public @interface ValidExcelFile {
String message() default "请上传有效的Excel文件(.xls 或 .xlsx 格式)";
}
3、新建 Excel文件校验器
src/main/java/com/weiyu/validation/ExcelFileValidator.java
package com.weiyu.validation;
import com.weiyu.annotation.ValidExcelFile;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import org.springframework.web.multipart.MultipartFile;
import java.util.Arrays;
import java.util.List;
/**
* Excel文件校验器
*/
public class ExcelFileValidator implements ConstraintValidator {
private static final List EXCEL_EXTENSIONS = Arrays.asList("xls", "xlsx");
private static final List EXCEL_CONTENT_TYPES = Arrays.asList(
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
);
@Override
public boolean isValid(MultipartFile file, ConstraintValidatorContext context) {
if (file == null || file.isEmpty()) {
return false;
}
// 校验文件名
String originalFilename = file.getOriginalFilename();
if (originalFilename == null) {
return false;
}
// 校验扩展名
String extension = getFileExtension(originalFilename).toLowerCase();
if (!EXCEL_EXTENSIONS.contains(extension)) {
return false;
}
// 校验Content-Type
String contentType = file.getContentType();
return contentType == null || EXCEL_CONTENT_TYPES.contains(contentType);
}
private String getFileExtension(String filename) {
int lastDotIndex = filename.lastIndexOf(".");
return lastDotIndex == -1 ? "" : filename.substring(lastDotIndex + 1);
}
}
浙公网安备 33010602011771号