Spring e Apache FileUpload

1. Panoramica

La libreria per il caricamento dei file di Apache Commons ci aiuta a caricare file di grandi dimensioni tramite il protocollo HTTP utilizzando il tipo di contenuto multipart / form-data .

In questo breve tutorial, daremo un'occhiata a come integrarlo con Spring.

2. Dipendenze di Maven

Per utilizzare la libreria, avremo bisogno dell'artefatto commons-fileupload :

 commons-fileupload commons-fileupload 1.3.3 

L'ultima versione può essere trovata su Maven Central.

3. Trasferimento tutto in una volta

A scopo dimostrativo, creeremo un controller che elabora le richieste con un payload di file:

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

All'inizio, dobbiamo controllare se la richiesta contiene un contenuto multiparte utilizzando il metodo isMultipartContent trovato nella classe ServletFileUpload dalla libreria.

Per impostazione predefinita, Spring presenta un MultipartResolver che dovremo disabilitare per utilizzare questa libreria. In caso contrario, leggerà il contenuto della richiesta prima che raggiunga il nostro Controller.

Possiamo ottenere ciò includendo questa configurazione nel nostro file application.properties :

spring.http.multipart.enabled=false

Ora possiamo impostare la directory in cui verranno salvati i nostri file, la soglia in cui la libreria decide di scrivere su disco e se i file devono essere eliminati al termine della richiesta.

La libreria fornisce una classe DiskFileItemFactory chesi assume la responsabilità della configurazione per il salvataggio e la pulizia dei file . Il metodo setRepository imposta la directory di destinazione, con il valore predefinito mostrato nell'esempio.

Successivamente, setSizeThreshold imposta una dimensione massima del file.

Quindi, abbiamo il metodo setFileCleaningTracker che, se impostato su null, lascia inalterati i file temporanei. Per impostazione predefinita, li elimina al termine della richiesta .

Ora possiamo continuare con l'effettiva gestione dei file.

Innanzitutto, creiamo il nostro ServletFileUpload includendo la nostra fabbrica creata in precedenza; si procede quindi ad analizzare la richiesta e generare un elenco di FileItem che sono l'astrazione principale della libreria per i campi del form.

Ora, se sappiamo che non è un normale campo modulo, procediamo a estrarre InputStream ea chiamare l'utile metodo di copia da IOUtils (per ulteriori opzioni puoi dare un'occhiata a questo tutorial) .

Ora abbiamo il nostro file memorizzato nella cartella necessaria. Questo di solito è un modo più conveniente per gestire questa situazione in quanto consente un facile accesso ai file, ma anche l'efficienza di tempo / memoria non è ottimale.

Nella sezione successiva, daremo uno sguardo all'API di streaming.

4. Streaming API

L'API di streaming è facile da usare, rendendola un ottimo modo per elaborare file di grandi dimensioni semplicemente non copiandoli in una posizione temporanea:

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

Possiamo vedere nel frammento di codice precedente che non includiamo più un DiskFileItemFactory . Questo perché, quando si utilizza l'API di streaming, non ne abbiamo bisogno .

Successivamente, per elaborare i campi, la libreria fornisce un FileItemIterator , che non legge nulla fino a quando non li estraiamo dalla richiesta con il metodo successivo .

Infine, possiamo vedere come ottenere i valori degli altri campi del modulo.

5. conclusione

In questo articolo, abbiamo esaminato come possiamo utilizzare la libreria di caricamento file di Apache Commons con Spring per caricare ed elaborare file di grandi dimensioni.

Come sempre il codice sorgente completo può essere trovato su GitHub.