在关闭的对话框窗口中单击下载按钮时,有时找不到StreamResource资源

时间:2019-03-14 13:33:44

标签: java vaadin vaadin10 vaadin-flow

我正在处理一个对话框,该对话框具有指向动态生成文件的下载链接  通过StreamResource,当用户单击下载按钮时,对话框应关闭。 很简单。但是,当用户打开对话框并单击下载按钮有时时,创建的文件已成功下载。问题是在其他时间,用户尝试下载创建的文件时可能会随机遇到“找不到资源/文件”错误消息。重现问题的代码段下方。

public class HomeView extends VerticalLayout{

Dialog dialog;

public HomeView() {
    //Set up dialog
    dialog = new Dialog();
    Button downloadButton = new Button("Download");
    //This might be the problem. Dialog might be closed before the download even starts?
    downloadButton.addClickListener(click -> dialog.close());
    Anchor anchor = new Anchor();
    anchor.add(downloadButton);
    anchor.setHref(new StreamResource("file", () -> createInputStream()));
    dialog.add(anchor);

    //Add a button to open dialog
    Button openDialog = new Button("Open Dialog");
    openDialog.addClickListener(click -> dialog.open());
    add(openDialog);
}

private InputStream createInputStream() {
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    try {
        outputStream.write("text".getBytes());
    } catch (IOException e) {
        e.printStackTrace();
    }
    return new ByteArrayInputStream(outputStream.toByteArray());
}

因此,有时用户在按下下载键时可能会遇到找不到资源的错误消息。

"Resource is not found for path" image

有趣的是,如果我在createInputStream()方法中关闭对话框,则不会收到错误消息。下面是一个例子。

public class HomeView extends VerticalLayout{

Dialog dialog;

public HomeView() {
    dialog = new Dialog();
    Button downloadButton = new Button("Download");
    //Commented out
    //downloadButton.addClickListener(click -> dialog.close());
    Anchor anchor = new Anchor();
    anchor.add(downloadButton);
    anchor.setHref(new StreamResource("file", () -> createInputStream()));
    dialog.add(anchor);

    Button openDialog = new Button("Open Dialog");
    openDialog.addClickListener(click -> dialog.open());
    add(openDialog);
}

private InputStream createInputStream() {
    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    try {
        outputStream.write("text".getBytes());
    } catch (IOException e) {
        e.printStackTrace();
    }
    //Close the dialog here
    dialog.close();
    return new ByteArrayInputStream(outputStream.toByteArray());
}

现在,无论我单击下载按钮多少次,都不会收到资源错误消息,并且对话框仍会按预期关闭。

我正在使用Vaadin 13.0.1。

所以最后我有这个问题。 第一个代码段无法在100%的时间内运行,但是第二个代码段似乎可以正常运行,为什么?

1 个答案:

答案 0 :(得分:1)

StreamResource在幕后工作,以便生成一个临时URL并将资源实例添加到以URL为键的地图上。然后,当浏览器向该URL发出请求时,它会被用于查找正确的内容以放入响应中。

为防止此操作无限期地泄漏内存,已实现该方法,以便在分离“所有者”组件时立即从该全局映射中删除资源。在您的情况下,anchor是所有者,并且在关闭对话框时确实是分离的。您观察到的随机性取决于哪个请求首先到达服务器。