在上传大文件时,我无法捕捉和优雅地处理公共文件上传FileUploadBase.SizeLimitExceededException
或弹簧。MaxUploadSizeExceededException
据我所知,这些异常是在数据绑定期间引发的,在实际到达控制器之前,因此导致 500 并且没有调用异常处理程序方法。以前有没有人遇到过这种情况,正确处理这些异常的最佳方法是什么?
在上传大文件时,我无法捕捉和优雅地处理公共文件上传FileUploadBase.SizeLimitExceededException
或弹簧。MaxUploadSizeExceededException
据我所知,这些异常是在数据绑定期间引发的,在实际到达控制器之前,因此导致 500 并且没有调用异常处理程序方法。以前有没有人遇到过这种情况,正确处理这些异常的最佳方法是什么?
感谢 thetoolman 提供了这个简单的解决方案。我把它延长了一点。我想保持文件处理不变并将异常传输到控制器。
package myCompany;
public class DropOversizeFilesMultipartResolver extends CommonsMultipartResolver {
/**
* Parse the given servlet request, resolving its multipart elements.
*
* Thanks Alexander Semenov @ http://forum.springsource.org/showthread.php?62586
*
* @param request
* the request to parse
* @return the parsing result
*/
@Override
protected MultipartParsingResult parseRequest(final HttpServletRequest request) {
String encoding = determineEncoding(request);
FileUpload fileUpload = prepareFileUpload(encoding);
List fileItems;
try {
fileItems = ((ServletFileUpload) fileUpload).parseRequest(request);
} catch (FileUploadBase.SizeLimitExceededException ex) {
request.setAttribute(EXCEPTION_KEY, ex);
fileItems = Collections.EMPTY_LIST;
} catch (FileUploadException ex) {
throw new MultipartException("Could not parse multipart servlet request", ex);
}
return parseFileItems(fileItems, encoding);
}
}
并在控制器中
@InitBinder("fileForm")
protected void initBinderDesignForm(WebDataBinder binder) {
binder.setValidator(new FileFormValidator());
}
@RequestMapping(value = "/my/mapping", method = RequestMethod.POST)
public ModelAndView acceptFile(HttpServletRequest request, Model model, FormData formData,
BindingResult result) {
Object exception = request.getAttribute(DropOversizeFilesMultipartResolver.EXCEPTION_KEY);
if (exception != null && FileUploadBase.SizeLimitExceededException.class.equals(exception.getClass())) {
result.rejectValue("file", "<your.message.key>");
LOGGER.error(exception);
}
弹簧配置保持不变。将异常传输到验证器会非常好,但我还没有弄清楚如何做到这一点。
我知道这很旧,但我也在寻找解决方案,但找不到任何东西。我们正在使用 Spring 提供 RESTful 服务,我们正在上传文件,但不知道如何处理。我想出了以下内容,希望它对某人有用:
我们所有的异常都用注释处理,所以我们的错误处理程序解析器设置如下:
@Configuration
public class MyConfig{
@Bean
public AnnotationMethodHandlerExceptionResolver exceptionResolver(){
final AnnotationMethodHandlerExceptionResolver resolver = new AnnotationMethodHandlerExceptionResolver();
resolver.setMessageConverters(messageConverters());
resolver;
}
}
然后是一个可以处理异常的通用类
public class MultipartExceptionHandler
{
@ExceptionHandler(MaxUploadSizeExceededException.class)
@ResponseStatus(value = HttpStatus.PRECONDITION_FAILED)
@ResponseBody
protected CustomError handleMaxUploadSizeExceededException(final HttpServletRequest request,
final HttpServletResponse response, final Throwable e)
throws IOException
{
logger.error(e);
CustomError c = new CustomErrorMaxFileSize("Max file size exceeded", MAX_FILE_SIZE);
return c;
}
@ExceptionHandler(MultipartException.class)
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
protected CustomError handleGenericMultipartException(final HttpServletRequest request,
final HttpServletResponse response, final Throwable e)
throws IOException
{
logger.error(e);
CustomError c = new CustomErrorGeneric("There was a problem with the upload");
return c;
}
}
然后我们继承commons multipart resolver并实现HandlerExceptionResolver接口
@Component(value="multipartResolver") // Spring expects this name
public class MyMultipartResolver extends CommonsMultipartResolver implements HandlerExceptionResolver
{
// This is the Spring bean that handles exceptions
// We defined this in the Java configuration file
@Resource(name = "exceptionResolver")
private AnnotationMethodHandlerExceptionResolver exceptionResolver;
// The multipart exception handler with the @ExceptionHandler annotation
private final MultipartExceptionHandler multipartExceptionHandler = new MultipartExceptionHandler();
// Spring will call this when there is an exception thrown from this
// multipart resolver
@Override
public ModelAndView resolveException(
final HttpServletRequest request,
final HttpServletResponse response,
final Object handlerParam,
final Exception ex)
{
// Notice that we pass this.multipartExceptionHandler
// and not the method parameter 'handlerParam' into the
// exceptionResolver. We do this because the DispatcherServlet
// doDispatch() method calls checkMultipart() before determining
// the handler for the request. If doing the multipart check fails
// with a MultipartException, Spring will never have a reference
// to the handler and so 'handlerParam' will be null at this point.
return exceptionResolver.resolveException(request, response, this.multipartExceptionHandler, ex);
}
}
这似乎是一个相当普遍的问题。我遇到过类似的问题,也有人问过类似的问题,例如看这个问题。我还没有看到解决这个问题的好方法。您可以使用 vanilla servlet 过滤器来处理这些异常,但这将重复您的错误处理,因为您已经有一个 ExceptionHandler。