Struts2 – il Result Type Stream

Definizione

Il Result Type Stream permette di restituire uno streaming di dati direttamente via HttpServletResponse. Si usa generalmente per gestire il download di files.

La sua definizione è molto semplice:

<result name="success" type="stream">
<param ...>...</param>
<param ...>...</param>
</result>

I parametri predefiniti per questo tipo di result sono:

  • contentType: ll mime-type che viene inviato al browser (default = text/plain).
  • contentLength: la lunghezza in bytes dello stream.
  • contentDisposition: il valore Content-Disposition ad appendere all’header dove è possibile specificare il nome del file (default = inline, tipicamente attachment;filename=”document.pdf”.
  • inputName: è l’InputStream vero e proprio (ci sarà una proprietà nella relativa classe che lo gestisce) (default = inputStream).
  • bufferSize: dimensione del buffer (default = 1024).
  • allowCaching: se a ‘false’ imposta gli header ‘Pragma’ and ‘Cache-Control’ a ‘no-cache’, ordinando quindi al client di non fare cache del contenuto. (default = true)
  • contentCharSet: se impostato, il suo valore verrà usato per valorizzare la stringa ‘;charset=valore’ che verrà aggiunta al content-type dell’header. Altrimenti non verrà aggiunto nessun charset all’header.

Esempio

Nell’esempio associato definisco una action download, in questo modo (dove non specificato il result type è tiles):

<action name="download" class="it.nicola.esempi.Download">
 
	<result type="stream">
		<param name="contentType">${contentType}</param>
		<param name="contentLength">${contentLength}</param>
		<param name="inputName">inputStream</param>
		<param name="contentDisposition">attachment;filename="${allegato}"</param>
		<param name="bufferSize">1024</param>
		<param name="allowCaching">false</param>
	</result>		
        [...]
</action>

La classe it.nicola.esempi.Download avrà le proprietà contentType, contentLength, allegato e l’InputStream inputStream (con i relativi get/set) e le valorizzerà nel suo metodo execute. In questo semplice esempio questa action prende in input il parametri id, e restituisce un file diverso ad un id diverso:

public class Download extends ActionSupport implements ServletRequestAware {
 
	private static final long serialVersionUID = 1L;
 
	private int id;
	private InputStream inputStream;
	private String contentType;
	private long contentLength;
	private String allegato;
	private HttpServletRequest request;
 
	public String execute() throws Exception {
 
		String contextPath = request.getSession().getServletContext().getRealPath(File.separator);
		String downloadPath = contextPath + "WEB-INF" + File.separator + "downloads" + File.separator;
 
		String nomeFile = "";
 
		switch (id) {
		case 1:
			contentType = "application/vnd.oasis.opendocument.spreadsheet";
			nomeFile = "documento.ods";
			allegato = "Documento.ods";
			break;
		case 2:
			contentType = "application/pdf";
			nomeFile = "documento.pdf";
			allegato = "Documento.pdf";
			break;
		case 3:
			contentType = "application/zip";
			nomeFile = "documento.zip";
			allegato = "Documento.zip";			
			break;
		case 4:
			contentType = "image/jpeg";
			nomeFile = "albertosordi.jpg";
			allegato = "Il vigile.jpg";			
			break;
		default:
 
			break;
		}
 
		File f = new File(downloadPath + nomeFile);
		setContentLength(f.length());
		inputStream = new FileInputStream(f);
 
		return "success";
	}
 
	...
	elenco get/set
	...
}

quindi, queste chiamate:

http://localhost:8180/esempio-struts2-download/download?id=1
http://localhost:8180/esempio-struts2-download/download?id=2
http://localhost:8180/esempio-struts2-download/download?id=3
http://localhost:8180/esempio-struts2-download/download?id=4

generano rispettivamente i download dei files specificati nel metodo execute. Mentre la chiamata

http://localhost:8180/esempio-struts2-download/download?id=5

genera un errore. Qualsiasi altro id genera il messaggio di file non trovato.

Conclusioni

Utilizzando questo result type, invece del link diretto al file, è possibile per esempio nascondere i files da scaricare sotto la WEB-INF, come ho fatto in questo progetto di prova, per gestire ad esempio il download sotto autenticazione, o un donwload manager che tenga traccia del numero di download effettuati.

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>