Spring und Apache FileUpload

1. Übersicht

Mit der Apache Commons File Upload Library können wir große Dateien über das HTTP-Protokoll mit dem Inhaltstyp Multipart / Formulardaten hochladen .

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 Artefakt commons-fileupload :

 commons-fileupload commons-fileupload 1.3.3 

Die neueste Version finden Sie auf Maven Central.

3. Alle auf einmal übertragen

Zu Demonstrationszwecken erstellen wir einen Controller , der Anforderungen mit einer Dateinutzlast verarbeitet:

@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 müssen wir mithilfe der isMultipartContent- Methode in der ServletFileUpload- Klasse aus der Bibliothek prüfen, ob die Anforderung einen mehrteiligen Inhalt enthält .

Standardmäßig verfügt Spring über einen MultipartResolver , den wir deaktivieren müssen, um diese Bibliothek verwenden zu können. Andernfalls wird der Inhalt der Anforderung gelesen, bevor sie unseren Controller erreicht.

Dies können wir erreichen, indem wir diese Konfiguration in unsere Datei application.properties 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 auf die Festplatte schreiben möchte, und festlegen, ob Dateien nach Ende der Anforderung gelöscht werden sollen.

Die Bibliothek bietet eine DiskFileItemFactory- Klasse, dieübernimmt die Verantwortung für die Konfiguration für das Speichern und Bereinigen von Dateien . Die Methode setRepository legt das Zielverzeichnis fest, wobei die Standardeinstellung im Beispiel angezeigt wird.

Als Nächstes legt setSizeThreshold eine maximale Dateigröße fest.

Dann haben wir die setFileCleaningTracker- Methode, die, wenn sie auf null gesetzt ist, die temporären Dateien unberührt lässt. Standardmäßig werden sie gelöscht, nachdem die Anforderung abgeschlossen wurde .

Jetzt können wir mit der eigentlichen Dateiverwaltung fortfahren.

Zuerst erstellen wir unser ServletFileUpload, indem wir unsere zuvor erstellte Factory einbeziehen . Anschließend analysieren wir die Anforderung und generieren eine Liste von FileItem, die die Hauptabstraktion der Bibliothek für die Formularfelder darstellt.

Wenn wir nun wissen, dass es sich nicht um ein normales Formularfeld handelt, extrahieren wir den InputStream und rufen die nützliche Kopiermethode von IOUtils auf (weitere Optionen finden Sie in diesem 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 werfen wir einen Blick auf die Streaming-API.

4. Streaming-API

Die Streaming-API ist einfach zu verwenden, sodass große Dateien einfach verarbeitet werden können, indem nicht an einen temporären Speicherort kopiert wird:

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 keine DiskFileItemFactory mehr einschließen . Dies liegt daran, dass wir die Streaming-API bei Verwendung nicht benötigen .

Um Felder zu verarbeiten, stellt die Bibliothek einen FileItemIterator bereit , der nichts liest, bis wir sie mit der nächsten Methode aus der Anforderung extrahieren .

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

5. Schlussfolgerung

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 finden Sie den vollständigen Quellcode bei GitHub.