2

目的是在服务器准备下载文件时显示等待微调器图标。在我的用例中,我正在生成一个大型报告,在调用浏览器的下载/另存为提示之前,服务器端需要一些时间。我可以向等待微调器展示没有问题,但找不到清除它的方法。

当前相关代码:

<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 的东西......

我尝试过的解决方案:

Usinga4j:commandButton提供了一个oncomplete事件,但该按钮会生成一个 AJAX 请求,该请求无法开始下载。(参见h:command button oncomplete action

使用window.timeout函数调用.stop()组件。这在功能层面上有效,但由于生成时间在 1-10 秒之间波动很大,这使得指标有点不反映现实。

有人对处理这个有什么好主意吗?

4

3 回答 3

1

一种方法是返回到同一页面,在其中有条件地呈现一段 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);
// ...
于 2013-06-17T16:23:25.530 回答
0

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

于 2013-06-14T20:10:42.307 回答
0

简单的解决方案是将 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 请求(这是异步的),并且当服务器响应时,回调函数会执行您想要的任何操作。看看这些参考资料:

于 2013-06-14T18:43:55.137 回答