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 マルチパート リゾルバーをサブクラス化し、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

これはかなり一般的な問題のようです。同様の問題があり、同様の質問がありました。たとえば、この質問を参照してください。私はまだ問題の良い解決策を見ていません。通常のサーブレット フィルターを使用してこれらの例外を処理できますが、既に ExceptionHandler があるため、エラー処理が重複します。

于 2010-10-27T07:43:49.813 に答える