发生MultipartException时,spring boot文件上载执行两次

时间:2016-01-04 08:35:31

标签: file-upload spring-boot

我想使用spring-boot上传文件,并且我已经正确配置了属性,并且我也确保控制器是正确的,但奇怪的是当我尝试上传大于超过限制的文件时控制器执行了两次,我所期待的是一个错误的json消息,而我得到的是Postman下没有回复。

这是我的控制器,

@RestController
public class FileUploadController implements HandlerExceptionResolver {
    private static final Logger LOGGER = LoggerFactory.getLogger(FileUploadController.class);

    private static final String UPLOAD_PATH = "upload";

    @ResponseBody
    @RequestMapping(value = "/upload", method = RequestMethod.POST, consumes = "multipart/form-data", produces = "application/json;charset=UTF-8")
    public String upload(final MultipartFile file) {
        try {
            final Result<String> result = new Result<>();
            if (file.isEmpty()) {
                result.setSuccess(false);
                result.setMessage("file is empty");
                return Constants.OBJECT_MAPPER.writeValueAsString(result);
            }

            final File outputFile = new File(UPLOAD_PATH, UUID.randomUUID().toString());
            FileUtils.writeByteArrayToFile(outputFile, file.getBytes());

            result.setSuccess(true);
            result.setMessage(outputFile.toString());
            return Constants.OBJECT_MAPPER.writeValueAsString(result);
        } catch (final Exception ex) {
            LOGGER.error(ex.getMessage(), ex);
            return ExceptionResultBuilder.build(ex);
        }
    }

    @Override
    public ModelAndView resolveException(final HttpServletRequest request, final HttpServletResponse response, final Object handler, final Exception ex) {
        final ModelAndView modelAndView = new ModelAndView();
        modelAndView.setView(new MappingJackson2JsonView());
        final Map<String, Object> map = new HashMap<>();
        map.put("success", false);
        if (ex instanceof MultipartException) {
            // if (LOGGER.isDebugEnabled()) {
            LOGGER.info(ex.getMessage(), ex);
            // }
            final Throwable rootCause = ((MultipartException) ex).getRootCause();
            if (rootCause instanceof SizeLimitExceededException) {
                map.put("message", "request too large");
            } else if (rootCause instanceof FileSizeLimitExceededException) {
                map.put("message", "file too large");
            } else {
                map.put("message", "其他异常: " + rootCause.getMessage());
            }
        } else {
            LOGGER.error(ex.getMessage(), ex);
        }
        modelAndView.addAllObjects(map);
        return modelAndView;
    }
}

这是我的文件上传属性代码段

# MULTIPART (MultipartProperties)
multipart.enabled=true
multipart.max-file-size=5Mb
multipart.max-request-size=10Mb

如果我尝试上传大于5M的文件,我会在Postman下得到如下结果(文件大小为5208k) enter image description here 如果我试图在5M和10M之间上传文件,我将收到此错误,(文件大小为9748k) enter image description here

我调试到控制器中,发现在单个上传中执行了两次resolveException方法。

有人给我一些提示吗?

2 个答案:

答案 0 :(得分:0)

这里有最新的代码列表,我仍然得到相同的结果,

@RestController
@ControllerAdvice
public class FileUploadController {
    private static final Logger LOGGER = LoggerFactory.getLogger(FileUploadController.class);

    private static final String UPLOAD_PATH = "upload";

    @RequestMapping(value = "/upload", method = RequestMethod.POST, consumes = "multipart/form-data", produces = "application/json;charset=UTF-8")
    public HttpEntity<?> upload(final MultipartFile file) {
        try {
            final Result<String> result = new Result<>();
            if (file == null || file.isEmpty()) {
                result.setSuccess(false);
                result.setMessage("上传的文件为空");
                return new ResponseEntity<Result<?>>(result, HttpStatus.OK);
            }

            final File outputFile = new File(UPLOAD_PATH, UUID.randomUUID().toString());
            FileUtils.writeByteArrayToFile(outputFile, file.getBytes());

            result.setSuccess(true);
            result.setMessage(outputFile.toString());
            return new ResponseEntity<Result<?>>(result, HttpStatus.OK);
        } catch (final Exception ex) {
            LOGGER.error(ex.getMessage(), ex);
            return ExceptionResultBuilder.build(ex);
        }
    }

    @ExceptionHandler(MultipartException.class)
    public HttpEntity<?> multipartExceptionHandler(final MultipartException exception) {
        LOGGER.error(exception.getMessage(), exception);
        try {
            final Result<String> result = new Result<>();
            result.setSuccess(false);

            final Throwable rootCause = ((MultipartException) exception).getRootCause();
            if (rootCause instanceof SizeLimitExceededException) {
                result.setMessage("请求过大");
            } else if (rootCause instanceof FileSizeLimitExceededException) {
                result.setMessage("文件过大");
            } else {
                result.setMessage("未知错误");
            }
            return new ResponseEntity<Result<?>>(result, HttpStatus.OK);
        } catch (final Exception ex) {
            LOGGER.error(ex.getMessage(), ex);
            return ExceptionResultBuilder.build(ex);
        }
    }
}

答案 1 :(得分:0)

我只是犯同样的错误并通过将流动的代码添加到我的控制器来修复它,祝你好运

@ExceptionHandler({ MultipartException.class, FileSizeLimitExceededException.class,
        SizeLimitExceededException.class })
public ResponseEntity<Attachment> handleUploadrException(HttpServletRequest request, Throwable ex) {
    Attachment result = new Attachment();
    result.setDescription(ex.getMessage());
    HttpStatus status = getStatus(request);
    return new ResponseEntity<Attachment>(result, status);
}



private HttpStatus getStatus(HttpServletRequest request) {
    Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
    if (statusCode == null) {
        return HttpStatus.INTERNAL_SERVER_ERROR;
    }
    return HttpStatus.valueOf(statusCode);
}