18

在上传大文件时,我无法捕捉和优雅地处理公共文件上传FileUploadBase.SizeLimitExceededException或弹簧。MaxUploadSizeExceededException

据我所知,这些异常是在数据绑定期间引发的,在实际到达控制器之前,因此导致 500 并且没有调用异常处理程序方法。以前有没有人遇到过这种情况,正确处理这些异常的最佳方法是什么?

4

3 回答 3

7

感谢 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);
    }

弹簧配置保持不变。将异常传输到验证器会非常好,但我还没有弄清楚如何做到这一点。

于 2011-11-08T02:07:57.177 回答
4

我知道这很旧,但我也在寻找解决方案,但找不到任何东西。我们正在使用 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);

    }
}
于 2012-09-10T18:56:51.637 回答
1

这似乎是一个相当普遍的问题。我遇到过类似的问题,也有人问过类似的问题,例如看这个问题。我还没有看到解决这个问题的好方法。您可以使用 vanilla servlet 过滤器来处理这些异常,但这将重复您的错误处理,因为您已经有一个 ExceptionHandler。

于 2010-10-27T07:43:49.813 回答