Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing file size limit (maxUploadSize) depending on the controller

I have a Spring MVC web with two different pages that have different forms to upload different files. One of them should have a limitation of 2MB, while the other should have a 50MB limitation.

Right now, I have this limitation in my app-config.xml:

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- one of the properties available; the maximum file size in bytes (2097152 B = 2 MB) -->
    <property name="maxUploadSize" value="2097152 "/>
</bean>

And I could resolve the maxUploadSize exception in my main controller like that:

@Override
public @ResponseBody
ModelAndView resolveException(HttpServletRequest arg0,
        HttpServletResponse arg1, Object arg2, Exception exception) {
    ModelAndView modelview = new ModelAndView();
        String errorMessage = "";
        if (exception instanceof MaxUploadSizeExceededException) {
            errorMessage =  String.format("El tamaño del fichero debe ser menor de  %s", UnitConverter.convertBytesToStringRepresentation(((MaxUploadSizeExceededException) exception)
                    .getMaxUploadSize()));

        } else {
            errorMessage = "Unexpected error: " + exception.getMessage();
        }
        saveError(arg0, errorMessage);
        modelview = new ModelAndView();
        modelview.setViewName("redirect:" + getRedirectUrl());
    }
    return modelview;
}

But this, obviously, only controlls the 2MB limit. How could I make the limitation for the 20MB one? I've tried this solution: https://stackoverflow.com/a/11792952/1863783, which updates the limitation in runtime. However, this updates it for every session and every controller. So, if one user is uploading a file for the first form, another using uploading in the second form should have the limitation of the first one...

Any help? thanks

like image 476
Goyo Avatar asked May 16 '13 11:05

Goyo


2 Answers

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
like image 157
naXa Avatar answered Nov 14 '22 15:11

naXa


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.

like image 4
Bhashit Parikh Avatar answered Nov 14 '22 15:11

Bhashit Parikh