如何防止有人快速点击Vaadin 8中的FileDownloader按钮?

时间:2018-03-02 08:55:47

标签: java vaadin vaadin8

使用Vaadin manual中的代码:

Button downloadButton = new Button("Download image");
FileDownloader fileDownloader = new FileDownloader(createResource());
fileDownloader.extend(downloadButton);

此示例代码的问题在于有人可以开始快速单击downloadButton不停止,并且可以在用户单击时快速生成动态创建的文件。有没有办法设置限制器,也就是说x次后阻止用户下载?此外,如果您快速点击此按钮,则会出现错误,特别是DefaultErrorHandler

至少我想要一种方法来阻止某人下载文件超过x次。最好还有像downloadButton.disableOnClick()这样的东西,但我似乎找不到下载完成后重新启用的方法,因为下载完成时没有挂钩通知你但主要是目标是阻止某人连续下载50倍。

3 个答案:

答案 0 :(得分:3)

为此:

  

但是在下载完成后我似乎找不到重新启用的方法,因为在下载完成时没有通知你的钩子

不,我不知道 - 从客户端获取浏览器的下载功能,告诉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") ); 就像:

    override func awakeFromNib() {
    self.addTarget(self, action:#selector(buttonClicked(sender:)), for: UIControlEvents.touchUpInside)
    isChecked = UserDefaults.standard.bool(forKey: "buttonChecked")
}

@objc func buttonClicked(sender: UIButton) {
    isChecked = !isChecked
    UserDefaults.standard.set(isChecked, forKey: "buttonChecked")

}

`

答案 1 :(得分:1)

以下是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,但语法看起来并没有改变。

答案 2 :(得分:0)

Viritin(Vaadin插件)DownloadButton现在支持在将内容发送到客户端时执行逻辑。要显示那些您需要启用Push或向您的UI添加轮询间隔的内容。

请参阅项目测试源中的示例代码。它使用Button中的disableOnClick功能,但在内容写入浏览器后重新启用按钮:

https://github.com/viritin/viritin/blob/master/viritin/src/test/java/org/vaadin/viritin/it/DownloadButtonExample.java