
En tapestry el proceso no es muy complicado, tan solo deberemos devolver un objeto que implemente la interfaz StreamResponse en el manejador de evento («event handler») que procesa la petición.
Aquí el código de parte de un manejador de evento que construye y devuelve un objeto que implementa la interfaz StreamResponse:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
... | |
@Inject | |
private ResponseCompressionAnalyzer responseCompressionAnalyzer; | |
... | |
StreamResponse onSuccessFromForm() throws Exception { | |
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |
OutputStream os = baos; | |
String contentEncoding = null; | |
if (responseCompressionAnalyzer.isGZipSupported()) { | |
os = new GZIPOutputStream(os, 128 * 1024); | |
contentEncoding = "gzip"; | |
} | |
... | |
os.write(...); | |
... | |
return new InputStreamResponse(nombre, contentEncoding, "application/octet-stream", new ByteArrayInputStream(os.toByteArray())); | |
} | |
... |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.appspot.mukomix.tapestry.misc; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.text.MessageFormat; | |
import org.apache.commons.lang3.StringUtils; | |
import org.apache.tapestry5.StreamResponse; | |
import org.apache.tapestry5.services.Response; | |
public class InputStreamResponse implements StreamResponse { | |
private String nombre; | |
private String contentEncoding; | |
private String contentType; | |
private InputStream stream; | |
public InputStreamResponse(String nombre, String contentEncoding, String contentType, InputStream stream) { | |
this.nombre = nombre; | |
this.contentEncoding = contentEncoding; | |
this.contentType = contentType; | |
this.stream = stream; | |
} | |
public String getContentEncoding() { | |
return contentType; | |
} | |
@Override | |
public String getContentType() { | |
return contentType; | |
} | |
@Override | |
public InputStream getStream() throws IOException { | |
return stream; | |
} | |
@Override | |
public void prepareResponse(Response response) { | |
if (StringUtils.isNotBlank(contentEncoding)) { | |
response.setHeader("Content-Encoding", contentEncoding); | |
} | |
response.setHeader("Content-Disposition", MessageFormat.format("attachment; filename=\"{0}\"", nombre)); | |
} | |
} |
En la siguiente entrada de documentación sobre Apache Tapestry puedes encontrar más entradas, ejemplos y documentación.
Para finalizar, decir que la forma indicada en este ejemplo para convertir el OutputStream al InputStream que necesita el objeto StreamResponse puede ser mejorado con el uso de un PipedInputStream. La manera indicada en el ejemplo con el ByteArrayOuputStream obliga a mantener en memoria el contenido completo generado antes de ser enviado al cliente además de no empezar a enviarlo hasta que se genera por completo, si se trata de unos pocos MiB puede ser suficiente pero si son varias decenas la aplicación puede presentar algún problema en el uso de memoria.
Referencia:
http://tapestry.apache.org
http://betterexplained.com/articles/how-to-optimize-your-site-with-gzip-compression/