Reputation: 1275
I am using Vaadin and I need to create a link to download a PDF file. However, I need to close the InputStream. But if I close it when the user clicks to download the PDF file it is closed and throws an Exception. Where the correct place to close it?
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);
}
Upvotes: 0
Views: 729
Reputation: 37008
You don't need to close the InputStream. Providing the StreamResource
an InputStreamFactory
will call your factory to create an fresh input stream and will always close it for you (see com.vaadin.flow.server.StreamResource.Pipe#accept
using try-with-resources).
But the problem here is, that you are providing a "constant" factory, that always returns the same IS. So the second download will now fail on the closed IS. You should actually implement the factory like a real factory and always return a new IS.
E.g.
StreamResource res = new StreamResource("10041328370.pdf", () ->
new FileInputStream(file));
Upvotes: 6
Reputation: 59
You should probably initialize the InputStream outside of your try catch statement. The scope of the stream is solely inside the try block, so closing it where you need to (outside of that block) is impossible since it no longer exists. Initialize it perhaps after you initialize your file:
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);
}
It may be good to move the StreamResource as well.
EDIT: To answer your question, it's less about where you close the stream and more about where you open it. Close it wherever you're done taking input.
Upvotes: -3