什么时候关闭 InputStream?

When to close the InputStream?

我正在使用 Vaadin,我需要创建一个 link 来下载 PDF 文件。 但是,我需要关闭 InputStream。但是,如果我在用户单击下载 PDF 文件时关闭它,它将关闭并抛出异常。关闭它的正确位置在哪里?

File file = new File("f:\10041328370.pdf");
Anchor a;
try{    
    InputStream is= new FileInputStream(file);          
    StreamResource res = new StreamResource("10041328370.pdf", () -> is );
    
    a = new Anchor(res, "click here to download");
    a.getElement().setAttribute("download", "downloaded-other-name.pdf");
    add(a);
    
    is.close(); //if close here, when the user to click in the anchor, we will get the error: Stream Closed.                

} catch (IOException e) {
    throw new RuntimeException(e.getMessage);
}

您应该在 try catch 语句之外初始化 InputStream。流的范围仅在 try 块内,因此不可能在需要的地方(在该块之外)关闭它,因为它不再存在。也许在您初始化文件后初始化它:

File file = new File("f:\10041328370.pdf");
InputStream is= new FileInputStream(file);  
Anchor a;
try{            
    StreamResource res = new StreamResource("10041328370.pdf", () -> is );
    
    a = new Anchor(res, "click here to download");
    a.getElement().setAttribute("download", "downloaded-other-name.pdf");
    add(a);
    
    is.close(); //if close here, when the user to click in the anchor, we will get the error: Stream Closed.               
} catch (IOException e) {
    throw new RuntimeException(e.getMessage);
}

最好也移动 StreamResource。

编辑:要回答您的问题,与关闭流的位置无关,而与打开流的位置有关。在完成输入后将其关闭。

您不需要关闭 InputStream。提供 StreamResourceInputStreamFactory 将调用您的工厂创建一个新的输入流,并将始终为您关闭它(请参阅 com.vaadin.flow.server.StreamResource.Pipe#accept 使用 try-with-resources).

但这里的问题是,您正在提供一个“常量”工厂,它总是 return 相同的 IS。所以第二次下载现在将在关闭的 IS 上失败。您实际上应该像真正的工厂一样实施工厂,并且总是 return 一个新的 IS。

例如

StreamResource res = new StreamResource("10041328370.pdf", () -> 
    new FileInputStream(file));