Changing file size limit (maxUploadSize) depending on the controller

眉间皱痕 提交于 2019-12-05 01:28:46

It may seem like not the best solution at first sight, but it depends on your requirements.

You can set a global option with maximum upload size for all controllers and override it with lower value for specific controllers.

application.properties file (Spring Boot)

spring.http.multipart.max-file-size=50MB

Upload controller with check

public void uploadFile(@RequestPart("file") MultipartFile file) {
    final long limit = 2 * 1024 * 1024;    // 2 MB
    if (file.getSize() > limit) {
        throw new MaxUploadSizeExceededException(limit);
    }
    StorageService.uploadFile(file);
}

In case of a file bigger than 2MB you'll get this exception in log:

org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size of 2097152 bytes exceeded

This is how it is possible: Override the DispatcherServlet class. An example would probably looke like the following:

public class CustomDispatcherServlet extends DispatcherServlet {

    private Map<String, MultipartResolver> multipartResolvers;

    @Override
    protected void initStrategies(ApplicationContext context) {
            super.initStrategies(context);
            initMultipartResolvers(context);
    }

    private void initMultipartResolvers(ApplicationContext context) {
            try {
                    multipartResolvers = new HashMap<>(context.getBeansOfType(MultipartResolver.class));
            } catch (NoSuchBeanDefinitionException ex) {
                    // Default is no multipart resolver.
                    this.multipartResolvers = Collections.emptyMap();
            }
    }

    @Override
    protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
            if (this.multipartResolvers.isEmpty() && this.multipartResolvers.get(0).isMultipart(request)) {
                    if (request instanceof MultipartHttpServletRequest) {
                            logger.debug("Request is already a MultipartHttpServletRequest - if not in a forward, "
                                    + "this typically results from an additional MultipartFilter in web.xml");
                    } else {
                            MultipartResolver resolver = getMultipartResolverBasedOnRequest(request);
                            return resolver.resolveMultipart(request);
                    }
            }
            // If not returned before: return original request.
            return request;
    }

    private MultipartResolver getMultipartResolverBasedOnRequest(HttpServletRequest request) {
            // your logic to check the request-url and choose a multipart resolver accordingly.
            String resolverName = null;
            if (request.getRequestURI().contains("SomePath")) {
                    resolverName = "resolver1";
            } else {
                    resolverName = "resolver2";
            }
            return multipartResolvers.get(resolverName);
    }
}

Assuming that you have configured multiple MultipartResolvers in your application-context (presumably named 'resolver1' and 'resolver2' in the example code).

Of course, when you configure the DispatcherServlet in your web.xml, you use this class instead of the Spring DispatcherServlet.

Another way: A MultipartFilter could be used as well. Just override the lookupMultipartResolver(HttpServletRequest request) method and look up the required resolver yourself. However, there are some ifs and buts to that. Look up the documentation before using that.

Mina Samy

There is an elegant solution here Spring Boot: ClassNotFoundException when configuring maxUploadSize of CommonMultipartResolver

you can modify your application application.properties file to change the max upload size as you want

public class BaseDispatcherServlet extends DispatcherServlet {
    @Override
    protected void doService(final HttpServletRequest request, final HttpServletResponse response) {
        CommonsMultipartResolver multipartResolver = (CommonsMultipartResolver) getMultipartResolver();
        if (requestURI.contains("uriWithLargeFileSize")) {
            multipartResolver.setMaxUploadSize(100 * 100L);
        }
    }
}                                                                                                                                                                                                                                                                                                                                                                                                                               

As the main author, and maintainer of Commons Fileupload, I'd propose the following, with regard to your usecase:

  • Have two instances of FileUploadBase, one with a max size of 2MB, and another with 20MB. Depending on the request details (for example, by looking on the URI), use one, or the other instance.
  • If you aren't using FileUpload directly (but Spring, Struts, or whatever in front), then, most likely, a change in Fileupload wouldn't suffice for you, because the Frontend won't support a possible new feature, at least not initially. In that case, I suggest that you start pushing the frontend developers to support your requirement. They can easily do that by creating an instance of FileUploadBase per request. (It's a lightweight object, as long as you're not using file trackers, or similar advanced features, so no problem with that.)
  • I am ready to review, and possibly accept patches by you, or others, that replace the current check for maxUploadSize with a Predicate, or something similar.

Jochen

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!