[英]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,然后通过设置窗体上的目标属性,最后钩在iframe的onload事件重定向服务器对该IFRAME响应。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.