使用Vaadin manual中的代码,我们有:
Button downloadButton = new Button("Download image");
FileDownloader fileDownloader = new FileDownloader(createResource());
fileDownloader.extend(downloadButton);
这个示例代码的问题是有人可以开始快速点击downloadButton
不停止,并且动态创建的文件将在用户可以点击时生成。有没有办法设置限制器,也就是说x次后阻止用户下载?此外,如果你快速点击这个,你会得到一个错误,特别是DefaultErrorHandler
。
至少我想要一种方法来阻止某人下载文件超过x次。最好还有像downloadButton.disableOnClick()
这样的东西,但我似乎找不到下载完成后重新启用的方法,因为下载完成后没有挂钩通知你,但主要目标是停止有人从连续下载50倍。
为了这:
但是在下载完成后我似乎无法找到重新启用的方法,因为下载完成时没有通知你的钩子
不,没有钩子 - 我不知道 - 从客户端获得浏览器的下载功能,告诉Vaadin何时下载准备就绪。
然而,可能是服务器端解决方案。
我相信你从Resource
和后一个工具创建StreamResource
:
@Override
public InputStream getStream() {
return s;
}
当流s
关闭时,可以认为下载已准备就绪。但是InputStream.close()
也没有钩子。为此,您可以为InputStream
实现包装器实现,例如:
@Slf4j
@RequiredArgsConstructor
public class CloseNotifyingInputStream extends InputStream {
@FunctionalInterface
public static interface InputStreamCloseListener {
public void onInputStreamClose(CloseNotifyingInputStream closeNotifyingInputStream);
}
private final InputStream wrappedStream;
private final InputStreamCloseListener closeListener;
@Override
public synchronized int read() throws IOException {
return wrappedStream.read();
}
@Override
public void close() throws IOException {
log.info("Download complete, closing stream");
closeListener.onInputStreamClose(this);
wrappedStream.close();
super.close();
}
}
使用这种包装器,您可以在回调函数的帮助下获得通知,然后处理您决定实现的任何按钮逻辑。
最终你在s
的getStream()
会像:
new CloseNotifyingInputStream(getTheActualInputStream(),
cnis -> log.info("Handling the btn logic")
);
`
以下是50次下载后禁用按钮的解决方案。我添加了按钮作为createResource的参数。如果它将保持在同一类中,则不一定需要该参数。
int downloaded = 0;
private StreamResource createResource(Button downloadButton) {
return new StreamResource(new StreamSource() {
@Override
public InputStream getStream() {
downloaded++;
if (downloaded > 50)
{
downloadButton.setEnabled(false);
}
.. generate your InputStream
}
}, "myImage.png");
}
免责声明:我使用的是Vaadin7,但语法看起来并没有改变。
Viritin(Vaadin插件)DownloadButton现在支持在将内容发送到客户端时执行逻辑。要显示那些您需要启用Push或向UI添加轮询间隔的内容。
请参阅项目测试源中的示例代码。它使用Button中的disableOnClick功能,但在内容写入浏览器后重新启用按钮: