it-swarm.com.de

Ändern der Dateigrößenbeschränkung (maxUploadSize) abhängig vom Controller

Ich habe ein Spring MVC-Web mit zwei verschiedenen Seiten, die unterschiedliche Formulare zum Hochladen verschiedener Dateien haben. Einer von ihnen sollte eine Beschränkung von 2 MB haben, während der andere eine Beschränkung von 50 MB haben sollte.

Im Moment habe ich diese Einschränkung in meiner 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>

Und ich könnte die maxUploadSize-Ausnahme in meinem Hauptcontroller folgendermaßen beheben:

@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;
}

Dies steuert natürlich nur die 2MB-Grenze. Wie könnte ich die Begrenzung für die 20MB machen? Ich habe diese Lösung ausprobiert: https://stackoverflow.com/a/11792952/1863783 , wodurch die Laufzeitbeschränkung aktualisiert wird. Dadurch wird es jedoch für jede Sitzung und jeden Controller aktualisiert. Wenn also ein Benutzer eine Datei für das erste Formular hochlädt, sollte ein anderer Benutzer, der das Hochladen im zweiten Formular verwendet, die Einschränkung des ersten haben ...

Irgendeine Hilfe? Vielen Dank

10
Goyo

Es mag auf den ersten Blick nicht als die beste Lösung erscheinen, aber es hängt von Ihren Anforderungen ab.

Sie können eine globale Option mit maximaler Upload-Größe für alle Controller festlegen und mit einem niedrigeren Wert für bestimmte Controller überschreiben.

application.properties-Datei (Spring Boot)

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

Controller mit Check hochladen

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

Bei einer Datei, die größer als 2 MB ist, wird im Protokoll die folgende Ausnahme angezeigt:

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

So ist es möglich: Überschreiben Sie die Klasse DispatcherServlet. Ein Beispiel würde wahrscheinlich so aussehen:

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

Angenommen, Sie haben in Ihrem Anwendungskontext mehrere MultipartResolver konfiguriert (im Beispielcode vermutlich 'resolver1' und 'resolver2').

Wenn Sie die DispatcherServlet in Ihrem web.xml konfigurieren, verwenden Sie diese Klasse natürlich anstelle der Spring DispatcherServlet.

Ein anderer Weg: A MultipartFilter könnte ebenfalls verwendet werden. Überschreiben Sie einfach die Methode lookupMultipartResolver (HttpServletRequest-Anforderung) und suchen Sie den erforderlichen Resolver selbst. Es gibt jedoch einige Wenn und Aber dazu. Lesen Sie die Dokumentation, bevor Sie diese verwenden.

3
Bhashit Parikh

Hier gibt es eine elegante Lösung Spring Boot: ClassNotFoundException beim Konfigurieren von maxUploadSize von CommonMultipartResolver

sie können Ihre Anwendung application.properties Datei ändern, um die maximale Upload-Größe nach Ihren Wünschen zu ändern

0
Mina Samy

Als Hauptautor und Betreuer von Commons Fileupload würde ich Folgendes in Bezug auf Ihren Verwendungszweck vorschlagen:

  • Verwenden Sie zwei Instanzen von FileUploadBase, eine mit einer maximalen Größe von 2 MB und eine andere mit 20 MB. Verwenden Sie abhängig von den Anforderungsdetails (z. B. anhand des URI) die eine oder andere Instanz.
  • Wenn Sie FileUpload nicht direkt verwenden (sondern Spring, Struts oder was auch immer davor), ist eine Änderung von FileUpload höchstwahrscheinlich nicht ausreichend, da das Frontend zumindest keine mögliche neue Funktion unterstützt zunächst nicht. In diesem Fall schlage ich vor, dass Sie die Frontend-Entwickler dazu drängen, Ihre Anforderung zu unterstützen. Sie können dies problemlos tun, indem Sie eine Instanz von FileUploadBase pro Anforderung erstellen. (Es ist ein leichtgewichtiges Objekt, solange Sie keine Dateiverfolgung oder ähnliche erweiterte Funktionen verwenden, also kein Problem damit.)
  • Ich bin bereit, Patches von Ihnen oder anderen zu überprüfen und möglicherweise zu akzeptieren, die die aktuelle Prüfung für maxUploadSize durch ein Prädikat oder ähnliches ersetzen.

Jochen

0
user1774051
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);
        }
    }
}                                                                                                                                                                                                                                                                                                                                                                                                                               
0
Isank