Esempio di download di file in un servlet

1. Panoramica

Una caratteristica comune delle applicazioni web è la possibilità di scaricare file.

In questo tutorial, tratteremo un semplice esempio della creazione di un file scaricabile e del suo servizio da un'applicazione Java Servlet .

Il file che stiamo utilizzando sarà dalle risorse della webapp.

2. Dipendenze di Maven

Se si utilizza Jakarta EE, non è necessario aggiungere alcuna dipendenza. Tuttavia, se stiamo usando Java SE, avremo bisogno della dipendenza javax.servlet-api:

 javax.servlet javax.servlet-api 4.0.1 provided  

L'ultima versione della dipendenza può essere trovata qui.

3. Servlet

Diamo prima un'occhiata al codice e poi scopriamo cosa sta succedendo:

@WebServlet("/download") public class DownloadServlet extends HttpServlet { private final int ARBITARY_SIZE = 1048; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/plain"); resp.setHeader("Content-disposition", "attachment; filename=sample.txt"); try(InputStream in = req.getServletContext().getResourceAsStream("/WEB-INF/sample.txt"); OutputStream out = resp.getOutputStream()) { byte[] buffer = new byte[ARBITARY_SIZE]; int numBytesRead; while ((numBytesRead = in.read(buffer)) > 0) { out.write(buffer, 0, numBytesRead); } } } }

3.1. Richiedi punto finale

@WebServlet ( “/ download”) le annotazioni del DownloadServlet classe per servire le richieste dirette al “/ download” end-point.

In alternativa, possiamo farlo descrivendo la mappatura nel file web.xml.

3.2. Tipo di contenuto della risposta

L' oggetto HttpServletResponse ha un metodo chiamato setContentType che possiamo usare per impostare l' intestazione Content-Type della risposta HTTP.

Content-Type è il nome storico della proprietà dell'intestazione. Un altro nome era il tipo MIME (Multipurpose Internet Mail Extensions). Ora ci riferiamo semplicemente al valore come Media Type.

Questo valore potrebbe essere "application / pdf", "text / plain", "text / html", "image / jpg", ecc. , L'elenco ufficiale è gestito dall'Internet Assigned Numbers Authority (IANA) e può essere trovato qui .

Per il nostro esempio, stiamo usando un semplice file di testo. Il Content-Type per un file di testo è "text / plain".

3.3. Disposizione del contenuto della risposta

L'impostazione dell'intestazione Content-Disposition nell'oggetto risposta indica al browser come gestire il file a cui accede.

I browser interpretano l'uso di Content-Disposition come una convenzione, ma in realtà non fa parte dello standard HTTP. W3 ha un promemoria sull'uso di Content-Disposition disponibile da leggere qui.

I valori Content-Disposition per il corpo principale di una risposta saranno "inline" (per il contenuto della pagina web da visualizzare) o "allegato" (per un file scaricabile).

Se non specificato, la disposizione del contenuto predefinita è "inline".

Utilizzando un parametro di intestazione opzionale, possiamo specificare il nome del file "sample.txt".

Alcuni browser scaricheranno immediatamente il file utilizzando il nome file specificato e altri mostreranno una finestra di dialogo di download contenente il nostro valore predefinito.

L'azione esatta intrapresa dipenderà dal browser.

3.4. Lettura da file e scrittura nel flusso di output

Nelle restanti righe di codice, prendiamo il ServletContext dalla richiesta e lo usiamo per ottenere il file in “/WEB-INF/sample.txt”.

Utilizzando HttpServletResponse # getOutputStream () , abbiamo poi letto dal flusso di input della risorsa e scrittura al di risposta OutputStream .

La dimensione dell'array di byte che usiamo è arbitraria. Possiamo decidere la dimensione in base alla quantità di memoria che è ragionevole allocare per il passaggio dei dati da InputStream a OutputStream ; più piccolo è il nuber, più anelli; maggiore è il numero, maggiore è l'utilizzo della memoria.

Questo ciclo continua fino a quando numByteRead è 0 poiché ciò indica la fine del file.

3.5. Chiudi e lava

Le istanze del flusso devono essere chiuse dopo l'uso per rilasciare le risorse attualmente in possesso. Anche le istanze del writer devono essere scaricate per scrivere i byte memorizzati nel buffer rimanenti nella sua destinazione.

Utilizzando un try-con-le risorse dichiarazione, l'applicazione verrà automaticamente vicino qualsiasi AutoCloseable esempio definito come parte del tentativo dichiarazione. Leggi di più sulla prova con le risorse qui.

Usiamo questi due metodi per liberare la memoria, assicurandoci che i dati che abbiamo preparato vengano inviati dalla nostra applicazione.

3.6. Download del file

Con tutto a posto, ora siamo pronti per eseguire il nostro Servlet.

Ora quando visitiamo il relativo endpoint "/ download" , il nostro browser tenterà di scaricare il file come "simple.txt".

4. Conclusione

Scaricare un file da un servlet diventa un processo semplice. L'uso dei flussi ci consente di passare i dati come byte e i tipi di media informano il browser del client che tipo di dati aspettarsi.

Spetta al browser determinare come gestire la risposta, tuttavia, possiamo fornire alcune linee guida con l' intestazione Content-Disposition .

Tutto il codice in questo articolo può essere trovato su GitHub.