2

在vaadin 7中,如何在使用时懒惰地确定文件名FileDownloader

final Button downloadButton = new Button("Download file");
FileDownloader downloader = new FileDownloader(new StreamResource(new StreamSource() {
    @Override
    public InputStream getStream () {
        return new ByteArrayInputStream(expesiveCalculationOfContent());
    }
}, "file.snub"));

downloader.extend(downloadButton);

在此代码示例中,文件名很明显

  1. 是垃圾
  2. 必须早日知道。

如何懒惰地确定下载文件的文件名?

4

3 回答 3

9

我不知道它是否脏,但这有效:扩展 FileDownloader.handleConnectorRequest() 以在调用其超级方法之前调用 StreamResource.setFilename()。

    {
        final Button downloadButton = new Button("Download file");
        final StreamResource stream = new StreamResource(
                new StreamSource() {
                    @Override
                    public InputStream getStream() {
                        return new ByteArrayInputStream("Hola".getBytes());
                    }
                }, "badname.txt");
        FileDownloader downloader = new FileDownloader(stream) {
            @Override
            public boolean handleConnectorRequest(VaadinRequest request,
                    VaadinResponse response, String path)
                    throws IOException {
                stream.setFilename("better-name.txt");
                return super
                        .handleConnectorRequest(request, response, path);
            }
        };

        downloader.extend(downloadButton);
        layout.addComponent(downloadButton);
    }
于 2013-04-04T21:40:11.833 回答
3

这是我想出的最终解决方案:

/**
 * This specializes {@link FileDownloader} in a way, such that both the file name and content can be determined
 * on-demand, i.e. when the user has clicked the component.
 */
public class OnDemandFileDownloader extends FileDownloader {

  /**
   * Provide both the {@link StreamSource} and the filename in an on-demand way.
   */
  public interface OnDemandStreamResource extends StreamSource {
    String getFilename ();
  }

  private static final long serialVersionUID = 1L;
  private final OnDemandStreamResource onDemandStreamResource;

  public OnDemandFileDownloader (OnDemandStreamResource onDemandStreamResource) {
    super(new StreamResource(onDemandStreamResource, ""));
    this.onDemandStreamResource = checkNotNull(onDemandStreamResource,
      "The given on-demand stream resource may never be null!");
  }

  @Override
  public boolean handleConnectorRequest (VaadinRequest request, VaadinResponse response, String path)
      throws IOException {
    getResource().setFilename(onDemandStreamResource.getFilename());
    return super.handleConnectorRequest(request, response, path);
  }

  private StreamResource getResource () {
    return (StreamResource) this.getResource("dl");
  }

}
于 2013-04-05T09:30:44.793 回答
0

如果假设延迟确定文件名意味着动态设置文件名而不管实际的文件系统名称可能是什么,那么下面的代码就是我正在使用的。

在下面的代码中,fileName 指向我们希望在下载时更改名称的本地文件系统文件。一个用例是当一个文件上传到 tmp 时,文件名包含一些原始上传中不存在的随机字符。

File file = new File(localFile);
final FileResource fileResource = new FileResource(file);
if (!file.exists()) {
   throw new IllegalStateException();
}
final StreamResource stream = new StreamResource(
                            new StreamSource() {
                                @Override
                                public InputStream getStream() {
                                    return fileResource.getStream().getStream();
                                }
                            }, "newname.txt");

FileDownloader fileDownloader = new FileDownloader(stream);
fileDownloader.extend(downloadButton);
于 2013-09-25T05:08:42.493 回答