繁体   English   中英

文件开始下载时触发​​javascript事件-收到响应后

[英]Fire javascript event when file starts to download - when response is received

目的是在服务器准备下载文件时显示一个等待微调图标。 在我的用例中,我正在生成一个大型报告,这需要花费服务器端一些时间才能调用浏览器的“下载/另存为”提示。 我可以显示等待微调程序没有问题,但是很难找到清除它的方法。

当前相关代码:

<h:commandButton id="generate" value="Generate Report" type="submit" 
    action="#{bean.generateReport()}" 
    onclick="#{rich:component('waitIcon')}.start();"/>

<a4j:status id="waitIcon">
     <f:facet name="start">
       <h:graphicImage value="/images/ai.gif" alt="ai" />
    </f:facet>
</a4j:status>

其中bean.generateReport()是需要在服务器端执行1-10秒的操作,然后吐出下载响应。

这使用了richfaces a4j:status指示器,因为它提供了有用的API,例如.start()和.stop(),但它也可以是任何dom元素和设置可见性。 问题是我无法获得正确的事件来进行跟踪。 我需要捕获类似onresponsereceived的内容...

我尝试过的解决方案:

使用a4j:commandButton提供一个oncomplete事件,但是该按钮生成一个AJAX请求,该请求无法启动下载。 (有关完成操作,请参见h:command按钮

使用window.timeout函数在组件上调用.stop() 这在功能级别上起作用,但是由于生成时间在1到10秒之间波动很大,因此该指标有点不能反映现实。

有人对此有什么好主意吗?

一种方法是返回到同一页面,在该页面中,您有条件地渲染一段JS代码,以启动实际下载。

<h:form>
    ...
    <h:commandButton value="submit" action="#{bean.prepareFileForDownload}" />
    <h:outputScript rendered="#{bean.fileReadyForDownload}">
        // Do here your thing to indicate start of download.
        window.location = '#{bean.fileDownloadURL}';
    </h:outputScript>
</h:form>

另一种方法是定期检查Cookie。 您只需生成URL安全值即可,因为它具有某种下载令牌( System.currentTimeMillis()完全适用于此)。

<h:form>
    ...
    <input type="hidden" name="token" value="#{bean.token}" />
    <h:commandButton value="submit" action="#{bean.downloadFile}" onclick="checkToken(this.form.token)" />
    <h:outputScript>
        function checkToken(token) {
            var pollDownloadStart = setInterval(function() {
                if (document.cookie.indexOf("download=" + token) > -1) {
                    document.cookie = "download=" + token + "; expires=" + new Date(0).toGMTString() + "; path=/";
                    clearInterval(pollDownloadStart);
                    // Do here your thing to indicate start of download.
                }
            }, 500);
         }
    </h:outputScript>
</h:form>

downloadFile()与此相关

// Prepare download here.
// ...

// Once finished, set cookie and stream download to response.
Cookie cookie = new Cookie("download", token);
cookie.setPath("/");
response.addCookie(cookie);
// ...

一种简单的解决方案是将setTimeout设置为1秒,以检查是否已接收到响应。 setTimeout将重复进行直到清除。

因此,您可以执行以下操作:

var responseReceived, hTimer = setTimeout( function() {
    if( responseReceived ) {
        // code to stop/hide spinner here
        clearTimeout( hTimer );
    }
}, 1000 );

// responseReceived is set when the response is received

另外,您需要的是编程术语中的彗星。 为了满足您的需求,Ajax长轮询应最适合您的需求。 基本上,您向服务器打开了一个ajax请求(这是异步的),并且当服务器响应时,回调函数会执行您想要的任何操作。 看一下这些参考:

如果我理解正确的话,你的用户填写表单中的一些数据,然后点击提交按钮,POST数据到,然后进行处理,一段时间后,它产生触发“另存为...”对话框窗口的响应服务器。 如果这是正确的,该解决方案是创建一个隐藏的iframe,然后通过设置窗体上的目标属性,最后钩在iframeonload事件重定向服务器对该IFRAME响应。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM