2011-10-04 22 views
18

DownloadLink là đẹp và tiện dụng cho việc tạo ra một nút/link để tải về một tập tin, cùng những dòng này:Làm thế nào để sử dụng DownloadLink của Wicket với một tập tin được tạo ra khi đang bay?

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

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

Tuy nhiên, tôi muốn kích hoạt việc tạo ra các tập tin để tải xuống chỉ khi nút/liên kết được nhấp vào. Nói cách khác, khi nhấp vào, tôi sẽ gọi một phương thức tạo tệp (báo cáo Pentaho trong trường hợp của chúng tôi), đặt nó ở vị trí tạm thời và trả về một dấu phẩy File trỏ đến nó. Sau đó, tôi sẽ yêu cầu DownloadLink sử dụng số File đó. Câu hỏi là, là điều này có thể bằng cách nào đó?

Hiện tại chúng tôi có một cái gì đó giống như mã bên dưới, hoạt động, nhưng tôi quan tâm đến việc liệu DownloadLink có thể được sử dụng thay thế hay không.

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 v1.4.18, nếu nó làm cho một sự khác biệt.)

Trả lời

15

bạn không thể sử dụng các nhà xây dựng mà phải mất một Model như là đối số? Và tạo Model tạo File trong số getObject(). A LoadableDetachableModel là một lựa chọn tốt, cho rằng load() và do đó tạo tệp, sẽ chỉ được gọi một lần.

Nếu tệp được tạo mới mỗi khi liên kết được nhấp, hãy sử dụng DownloadLink.setDeleteAfterDownload(true) để đảm bảo tệp sẽ tự động bị xóa sau khi được phân phát.

Tôi không sử dụng 1,4, nhưng mã nguồn trong 1.3 cho thấy rằng File được truy xuất bằng phương tiện getModelObject() trong phương thức onClick() của Link.

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

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

Source code của 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

Bạn cũng có thể ghi đè lên onClick của DownloadLink và thực hiện 'setModelObject()' trước khi gọi phương thức siêu. Tuy nhiên, gợi ý của Xavi là sạch hơn nhiều. – jbrookover

+4

1. Sử dụng 'LoadableDetachableModel' để thay thế. 'getObject()' có thể được gọi nhiều lần trong một yêu cầu, nhưng 'load()' sẽ không; 2. Nếu tệp luôn được tạo lại, bạn có thể gọi 'downloadLink.setDeleteAfterDownload (true)', vì vậy bạn không phải lo lắng về việc xóa tệp tạm thời sau đó. – tetsuo

+0

@tetsuo Cảm ơn những nhận xét quý giá của bạn. Tôi đã cập nhật câu trả lời với các đề xuất của bạn. –

10

Sử dụng org.apache.wicket.markup.html.link.ResourceLink để thay thế.

+0

Lợi ích của việc sử dụng ResourceLink thay vì DownloadLink (như [được hiển thị bởi Xavi López] (http://stackoverflow.com/questions/7646270/using-wickets-downloadlink-so-that-the-file-is-generated- khi-the-link-is-clicke/7646332 # 7646332))?(Không chắc chắn nếu nó có liên quan, nhưng lưu ý rằng ở đây các tập tin để tải xuống không phải là một tài nguyên tĩnh, nhưng một báo cáo năng động mà luôn luôn tạo ra một lần nữa.) – Jonik

+0

DownloadLink làm việc với java.io.File, trong khi ResourceLink làm việc với IResource. Có một số triển khai của IResource đến với Wro distro hầu hết trong số đó tạo ra dữ liệu động. –

Các vấn đề liên quan