第二次单击带有 StreamResource 的 Vaadin link 不起作用

Second click to Vaadin link with StreamResource doesn't work

我有一个来自另一台服务器的 InputStream(来自 JasperReports 的 PDF 文件)并且用户可以下载它。

...
VerticalLayout content;
OperationResult<InputStream> jresult;
...
final InputStream ent=jresult.getEntity();
if (ent.available()<=0) return;
Link link = new Link();
link.setCaption("Download the report");
link.setResource(new StreamResource(new StreamSource(){
    private static final long serialVersionUID = 1L;
    @Override
    public InputStream getStream() {
        return ent;
        }
}, "FileName.pdf"));
content.addComponent(link);

如果打印服务器returns页面,"Download the report"会出现,用户可以点击下载PDF文件。但是第二次点击同一个 link 失败。它可能 returns 空内容。怎么了?也许我必须倒回输入流。怎么样?

那是因为您的 getStream() 方法 return 是相同的流,而流预计只会从中读取一次。一旦你消费了流中的数据,数据就不再可用了。

您可能需要先使用此方法将 InputStream 转换为字节 (taken from this SO question)

public static byte[] readFully(InputStream stream) throws IOException
{
    byte[] buffer = new byte[8192];
    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    int bytesRead;
    while ((bytesRead = stream.read(buffer)) != -1)
    {
        baos.write(buffer, 0, bytesRead);
    }
    return baos.toByteArray();
}

然后在 getStream() 方法中 return 每次新的 InputStream:

@Override
public InputStream getStream() {
    return new ByteArrayInputStream(ent);
}

编辑解决方案 #2:就像@Hink 在评论中建议的那样,您也可以在 Stream 对象上调用 reset()。