Spring und Apache FileUpload

Spring und Apache FileUpload

1. Überblick

MitApache Commons File Upload Library können wir große Dateien über das HTTP-Protokoll mit dem Inhaltstypmultipart/form-datahochladen.

In diesem kurzen Tutorial werden wir uns ansehen, wie man es in Spring integriert.

2. Maven-Abhängigkeiten

Um die Bibliothek nutzen zu können, benötigen wir das Artefaktcommons-fileupload:


    commons-fileupload
    commons-fileupload
    1.3.3

Die neueste Version finden Sie unterMaven Central.

3. Alles auf einmal übertragen

Zu Demonstrationszwecken erstellen wir Verarbeitungsanforderungen fürControllermit einer Dateinutzlast:

@PostMapping("/upload")
public String handleUpload(HttpServletRequest request) throws Exception {
    boolean isMultipart = ServletFileUpload.isMultipartContent(request);

    DiskFileItemFactory factory = new DiskFileItemFactory();
    factory.setRepository(
      new File(System.getProperty("java.io.tmpdir")));
    factory.setSizeThreshold(
      DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD);
    factory.setFileCleaningTracker(null);

    ServletFileUpload upload = new ServletFileUpload(factory);

    List items = upload.parseRequest(request);

    Iterator iter = items.iterator();
    while (iter.hasNext()) {
        FileItem item = iter.next();

        if (!item.isFormField()) {
            try (
              InputStream uploadedStream = item.getInputStream();
              OutputStream out = new FileOutputStream("file.mov");) {

                IOUtils.copy(uploadedStream, out);
            }
        }
    }
    return "success!";
}

Zu Beginn verwendenwe need to check if the request contains a multipart content die MethodeisMultipartContent, die in der KlasseServletFileUpload aus der Bibliothek gefunden wurde.

StandardmäßigSpring features aMultipartResolverthat we’ll need to disable to use this library. Andernfalls wird der Inhalt der Anforderung gelesen, bevor er unsereController. erreicht

Wir können dies erreichen, indem wir diese Konfiguration in unsereapplication.properties-Datei aufnehmen:

spring.http.multipart.enabled=false

Jetzt können wir das Verzeichnis festlegen, in dem unsere Dateien gespeichert werden sollen, den Schwellenwert, in dem die Bibliothek beschließt, auf die Festplatte zu schreiben, und ob Dateien nach dem Ende der Anforderung gelöscht werden sollen.

Die Bibliothek stellt eineDiskFileItemFactory-Klasse bereit, mit der die Methode_ takes the responsibility of the configuration for the file saving and cleaning. The _setRepositorydas Zielverzeichnis festlegt. Die Standardeinstellung wird im Beispiel angezeigt.

Als nächstes legtsetSizeThreshold eine maximale Dateigröße fest.

Dann haben wir diesetFileCleaningTracker-Methode, die, wenn sie auf null gesetzt wird, die temporären Dateien unberührt lässt. By default, it deletes them after the request has finished.

Nun können wir mit der eigentlichen Dateiverwaltung fortfahren.

Zuerst erstellen wir unsereServletFileUpload, indem wir unsere zuvor erstellte Factory einbeziehen. Anschließend analysieren wir die Anforderung und generieren eine Liste vonFileItem, die die Hauptabstraktion der Bibliothek für die Formularfelder darstellen.

Wenn wir nun wissen, dass es sich nicht um ein normales Formularfeld handelt, extrahieren wirInputStream und rufen die nützliche Kopiermethode ausIOUtils auf (weitere Optionen finden Sie unterthis) s Tutorial).

Jetzt haben wir unsere Datei im erforderlichen Ordner gespeichert. Dies ist normalerweise eine bequemere Methode, um mit dieser Situation umzugehen, da sie einen einfachen Zugriff auf die Dateien ermöglicht, aber auch die Zeit- / Speichereffizienz nicht optimal ist.

Im nächsten Abschnitt werden wir uns die Streaming-API ansehen.

4. Streaming-API

Die Streaming-API ist einfach zu verwenden und bietet eine hervorragende Möglichkeit, große Dateien zu verarbeiten, indem Sie nicht an einen temporären Speicherort kopieren:

ServletFileUpload upload = new ServletFileUpload();
FileItemIterator iterStream = upload.getItemIterator(request);
while (iterStream.hasNext()) {
    FileItemStream item = iterStream.next();
    String name = item.getFieldName();
    InputStream stream = item.openStream();
    if (!item.isFormField()) {
        // Process the InputStream
    } else {
        String formFieldValue = Streams.asString(stream);
    }
}

Wir können im vorherigen Codefragment sehen, dass wir keinDiskFileItemFactory mehr einschließen. Dies liegt daran, dasswhen using the streaming API, we don’t need it.

Um Felder zu verarbeiten, stellt die Bibliothek einFileItemIterator bereit, das nichts liest, bis wir sie mit dernext-Methode aus der Anforderung extrahieren.

Schließlich können wir sehen, wie die Werte der anderen Formularfelder erhalten werden.

5. Fazit

In diesem Artikel haben wir untersucht, wie wir die Apache Commons File Upload Library mit Spring zum Hochladen und Verarbeiten großer Dateien verwenden können.

Wie immer kann der vollständige Quellcodeover at GitHub gefunden werden.