簡體   English   中英

StreamResource 有時在關閉對話框窗口中單擊下載按鈕時找不到資源

[英]StreamResource sometimes resource not found when clicking download button in a closing dialog window

我正在處理一個對話框,該對話框具有通過 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());
}

因此,用戶有時可能會在按下下載時遇到資源未找到錯誤消息。

“找不到路徑的資源”圖像

有趣的是,如果我在 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% 工作,但第二個代碼段似乎可以,為什么?

在幕后, StreamResource會生成一個臨時 URL,並將資源實例添加到以 URL 作為鍵的映射中。 然后,當瀏覽器向該 URL 發出請求時,這將用於查找要放入響應中的正確內容。

為了防止這種情況無限期地泄漏內存,它被實現為在“所有者”組件分離時立即從該全局映射中刪除資源。 在您的情況下, anchor是所有者,並且在關閉對話框時它確實是分離的。 您觀察到的隨機性取決於哪個請求首先到達服務器。

因此,Anchor 不應該在 Dialog 中,而是作為視圖本身中的不可見組件,您在 Button click 事件中觸發。 Gist 中有一個完整的代碼示例:

https://gist.github.com/TatuLund/0a0e7bdc1d182394c99fe2adfa3e7c6e

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM