2011-10-04 5 views
18

DownloadLink es agradable y práctico para la creación de un botón/enlace para descargar un archivo, a lo largo de estas líneas:¿Cómo utilizar el DownloadLink de Wicket con un archivo generado sobre la marcha?

add(new DownloadLink("downloadButton", getReportFile(), "report.pdf")); 

y

<input type="button" wicket:id="downloadButton" value="Download" /> 

Sin embargo, me gustaría gatillo de la generación del archivo para descargar solo cuando se hace clic en el botón/enlace. En otras palabras, al hacer clic, llamaría a un método que genera el archivo (un informe de Pentaho en nuestro caso), lo coloca en un lugar temporal y devuelve un File apuntando a él. Luego le diría al DownloadLink que use ese File. La pregunta es, ¿Es esto posible de alguna manera?

Actualmente tenemos algo así como el código siguiente, que funciona, pero estoy interesado en si podría usarse DownloadLink en su lugar.

add(new Link<Void>("downloadButton") { 
    @Override 
    public void onClick() { 
    IResourceStream resourceStream = new AbstractResourceStreamWriter() { 
     @Override 
     public void write(OutputStream output) { 
     try { 
      reportService.generateReport(output, report); 
     } catch (IOException e) { 
      // ... 
     } 
     } 

     @Override 
     public String getContentType() {       
     return CONTENT_TYPE_PDF; 
     } 
    }; 

    getRequestCycle() 
     .setRequestTarget(new ResourceStreamRequestTarget(resourceStream) 
     .setFileName("report.pdf")); 
    } 
}); 

(1.4.18 Wicket, si se hace una diferencia.)

Respuesta

15

no se puede utilizar el constructor que toma un Model como argumento? Y haga que el Model genere el File en su getObject(). Un LoadableDetachableModel es una buena opción, dado que load(), y por lo tanto la generación de archivos, se invocará solo una vez.

Si el archivo se va a generar recientemente cada vez que se hace clic en el enlace, utilice DownloadLink.setDeleteAfterDownload(true) para asegurarse de que el archivo se elimine automáticamente una vez que se sirve.

No consumo 1,4, pero el código fuente en 1.3 muestra que la File se recupera por medio de getModelObject() en el método de la LinkonClick().

IModel fileModel = new AbstractReadOnlyModel(){ 
    public Object getObject() { 
     return generateFile(); 
    } 
}; 

DownloadLink link = new DownloadLink(linkId, fileModel, "report.pdf"); 

El código fuente de DownloadLink.onClick()

public void onClick() 
{ 
    final File file = (File)getModelObject(); 
      ... 
    IResourceStream resourceStream = new FileResourceStream(
      new org.apache.wicket.util.file.File(file)); 
    getRequestCycle().setRequestTarget(.../* uses resourceStream */...); 
} 
+2

También puede anular el onClick de DownloadLink y hacer un 'setModelObject()' antes de llamar al método super. La sugerencia de Xavi es mucho más limpia, sin embargo. – jbrookover

+4

1. Use un 'LoadableDetachableModel' en su lugar. 'getObject()' puede llamarse varias veces durante una solicitud, pero 'load()' no; 2. Si el archivo siempre se vuelve a generar, puede llamar a 'downloadLink.setDeleteAfterDownload (true)', por lo que no tendrá que preocuparse por eliminar el archivo temporal después. – tetsuo

+0

@tetsuo Gracias por sus valiosos comentarios. He actualizado la respuesta con tus recomendaciones. –

10

Uso org.apache.wicket.markup.html.link.ResourceLink lugar.

+0

¿Cuál es el beneficio de utilizar ResourceLink en lugar de DownloadLink (como [mostrado por Xavi López]) (http://stackoverflow.com/questions/7646270/using-wickets-downloadlink-so-that-the-file-is-generated- when-the-link-is-clicke/7646332 # 7646332))?(No estoy seguro si es relevante, pero tenga en cuenta que aquí el archivo para descargar no es un recurso estático, sino un informe dinámico que siempre se genera de nuevo.) – Jonik

+0

DownloadLink funciona con java.io.File, mientras que ResourceLink funciona con IResource. Hay varias implementaciones de IResource que vienen con la distribución Wicket, la mayoría de las cuales generan datos dinámicos. –

Cuestiones relacionadas