【问题标题】:How to use Wicket's DownloadLink with a file generated on the fly?如何将 Wicket 的 DownloadLink 与动态生成的文件一起使用?
【发布时间】:2011-10-04 10:08:49
【问题描述】:

DownloadLink 非常适合创建用于下载文件的按钮/链接,如下所示:

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

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

但是,我想仅在单击按钮/链接时触发生成要下载的文件。换句话说,在单击时,我会调用一个方法来生成文件(在我们的例子中是 Pentaho 报告),将它放在一个临时位置并返回一个指向它的 File。然后我会告诉DownloadLink 使用File。问题是,这是否可能

目前我们有类似下面的代码,它可以工作,但我对是否可以使用 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,如果它有所作为的话。)

【问题讨论】:

    标签: java download wicket


    【解决方案1】:

    你不能使用以Model 作为参数的构造函数吗?并使Model 在其getObject() 中生成FileLoadableDetachableModel 是一个不错的选择,因为 load() 以及因此文件生成只会被调用一次。

    如果要在每次单击链接时重新生成文件,请使用DownloadLink.setDeleteAfterDownload(true) 确保文件在提供后自动删除。

    我没有使用1.4,但是1.3中的源码显示File是通过LinkonClick()方法中的getModelObject()获取的。

    IModel fileModel = new AbstractReadOnlyModel(){
        public Object getObject() { 
            return generateFile();
        }
    };
    
    DownloadLink link = new DownloadLink(linkId, fileModel, "report.pdf");
    

    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 */...);
    }
    

    【讨论】:

    • 您也可以覆盖 DownloadLink 的 onClick 并在调用 super 方法之前执行setModelObject()。不过,哈维的建议要干净得多。
    • 1.请改用LoadableDetachableModelgetObject() 可以在请求期间多次调用,但 load() 不会; 2.如果总是重新生成文件,可以拨打downloadLink.setDeleteAfterDownload(true),这样以后就不用担心删除临时文件了。
    • @tetsuo 感谢您宝贵的 cmets。我已根据您的建议更新了答案。
    • 谢谢!得到它的工作方式。还要感谢@tetsuo 提到setDeleteAfterDownload(true),这正是我所需要的。
    • 您可能需要在DownloadLink 上调用setCacheDuration(Duration.NONE) 以强制浏览器重新请求文件并重新生成对象。
    【解决方案2】:

    改用 org.apache.wicket.markup.html.link.ResourceLink。

    【讨论】:

    • 使用 ResourceLink 代替 DownloadLink 有什么好处(如 shown by Xavi López)? (不确定是否相关,但请注意这里要下载的文件不是静态资源,而是始终重新生成的动态报告。)
    • DownloadLink 与 java.io.File 一起使用,而 ResourceLink 与 IResource 一起使用。 Wicket 发行版附带了几种 IResource 实现,其中大多数会生成动态数据。
    猜你喜欢
    • 1970-01-01
    • 2013-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多