2011-10-04 4 views
18

DownloadLink è bello e utile per creare un pulsante/link per il download di un file, in questo senso:Come utilizzare DownloadLink di Wicket con un file generato al volo?

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

e

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

Tuttavia, vorrei grilletto la generazione del file per scaricare solo quando si fa clic sul pulsante/collegamento. In altre parole, al clic, chiamerei un metodo che genera il file (un rapporto Pentaho nel nostro caso), lo colloca in un luogo temporaneo e restituisce un File puntandolo. Quindi direi allo DownloadLink di usare quello File. Domanda è, questo è possibile in qualche modo?

Attualmente abbiamo qualcosa come il seguente codice, che funziona, ma mi interessa sapere se è possibile utilizzare DownloadLink.

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

(Wicket 1.4.18, se fa la differenza.)

risposta

15

non è possibile utilizzare il costruttore che prende un Model come argomento? E rendere il Model generare il File nel suo getObject(). Un LoadableDetachableModel è una buona scelta, dato che load(), e quindi la generazione di file, verrà invocato una sola volta.

Se il file deve essere appena generato ogni volta che si fa clic sul collegamento, utilizzare DownloadLink.setDeleteAfterDownload(true) per assicurarsi che il file venga automaticamente eliminato una volta servito.

non uso 1,4, ma il codice sorgente in 1.3 mostra che il File viene recuperato mediante getModelObject() nel metodo della LinkonClick().

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

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

Il codice sorgente di 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

È anche possibile eseguire l'override di onClick di DownloadLink e fare un 'setModelObject()' prima di chiamare il metodo super. Il suggerimento di Xavi è molto più pulito, però. – jbrookover

+4

1. Utilizzare invece un 'LoadableDetachableModel'. 'getObject()' può essere chiamato più volte durante una richiesta, ma 'load()' non lo farà; 2. se il file viene sempre rigenerato, puoi chiamare 'downloadLink.setDeleteAfterDownload (true)', quindi non dovrai più preoccuparti dell'eliminazione del file temporaneo. – tetsuo

+0

@tetsuo Grazie per i vostri preziosi commenti. Ho aggiornato la risposta con i tuoi consigli. –

10

Usa org.apache.wicket.markup.html.link.ResourceLink invece.

+0

Qual è il vantaggio dell'utilizzo di ResourceLink invece di DownloadLink (come [mostrato da Xavi López] (http://stackoverflow.com/questions/7646270/using-wickets-downloadlink-so-that-the-file-is-generated- quando-il-link-è-clicke/7.646.332 # 7.646.332))?(Non so se è rilevante, ma tieni presente che qui il file da scaricare non è una risorsa statica, ma un rapporto dinamico che viene sempre generato di nuovo.) – Jonik

+0

DownloadLink funziona con java.io.File, mentre ResourceLink funziona con IResource. Esistono diverse implementazioni di IResource in arrivo con la distribuzione di Wicket, la maggior parte delle quali genera dati dinamici. –