【问题标题】:How to prevent someone from rapid clicking on a FileDownloader button in Vaadin 8?如何防止有人快速点击 Vaadin 8 中的 FileDownloader 按钮?
【发布时间】:2018-03-02 08:55:47
【问题描述】:

使用来自Vaadin manual 的代码我们有:

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

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

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

【问题讨论】:

  • 当你点击后禁用按钮?
  • 主要问题是如何防止有人连续下载 50x。忽略这不是您如何重新启用按钮,而是何时?下载完成后,没有任何挂钩可让您知道。
  • 可以阻止下载 10 秒然后重新启用它吗?
  • 不是真的,因为我们确实有一些人需要稍微调整报告设置(更改日期)并重新运行它。基本上,我试图防止有人点击相同生成的报告的垃圾邮件。

标签: java vaadin vaadin8


【解决方案1】:

为此:

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

不,没有任何钩子——据我所知——从客户端获取浏览器的下载功能来告诉 Vaadin 何时准备好下载。

不过这可能是服务器端解决方案。

我相信你从StreamResource 创建Resource 并在后面实现:

@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();
    }
}

使用这种包装器,您可以借助回调函数获得通知,然后处理您决定实现的任何按钮逻辑。

最终你在getStream() 中的s 会是这样的:

new CloseNotifyingInputStream(getTheActualInputStream(),
            cnis -> log.info("Handling the btn logic")
);

`

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 这和我现在所做的差不多。问题是我以50为例,防止人意外双击等也很好。
    • 好吧,您可以通过阻止按钮一段时间来禁用双击。 1s 可以解决这个问题。但我认为 pirhos 解决方案更好,更符合您的要求!
    【解决方案3】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多