在p:fileDownload开始时显示状态并在完成后隐藏状态

10

我希望在执行zipManager.makeZip()期间显示ajaxStatus,直到下载开始。 如果ajax=false,则文件下载正常,但未显示ajaxStatus。 如果ajax=true,则显示ajaxStatus但下载不起作用!

您有任何想法如何使ajaxStatus和文件下载一起工作。

提前致谢

kem

<h:form id="form">
    <p:commandLink id="download" value="Download"
        onstart="showStatus()" oncomplete="hideStatus()" 
        actionListener="#{zipManager.makeZip()}">
        <p:fileDownload value="#{zipManager.zip}"/>  
    </p:commandLink>
</h:form>

<p:ajaxStatus id="status" widgetVar="st" style="position:fixed;right:50%;bottom:50%">  
    <f:facet name="start">  
        <p:graphicImage value="images/wait.gif" />  
    </f:facet>  
</p:ajaxStatus>
1个回答

20
如果ajax=false,文件下载可以正常工作,但是ajaxStatus不会显示。这是因为下载并不是通过ajax请求进行的。
如果ajax=true,将显示ajaxStatus但无法下载!这是因为通过ajax请求无法进行下载。JS/Ajax将成功检索文件,但不知道如何处理它。没有办法用JS强制启动“另存为”对话框。没有办法使用JS访问本地磁盘文件系统(否则将成为巨大的安全漏洞)。

有什么办法让ajaxStatus和fileDownload一起工作?

使用PrimeFaces提供的PrimeFaces.monitorDownload() JS函数。完整的示例可以在他们自己的<p:fileDownload>展示页面上找到,以下是该页面的复制内容(特别注意文件下载命令按钮的onclick属性):

<p:dialog modal="true" widgetVar="statusDialog" header="Status" 
    draggable="false" closable="false" resizable="false">  
    <p:graphicImage value="/design/ajaxloadingbar.gif" />  
</p:dialog>  

<h:form id="form">  
    <p:commandButton id="downloadLink" value="Download" ajax="false"
        onclick="PrimeFaces.monitorDownload(start, stop)"
        icon="ui-icon-arrowthichk-s">  
        <p:fileDownload value="#{fileDownloadController.file}" />  
    </p:commandButton>  
</h:form>  

<script type="text/javascript">  
    function start() {  
        statusDialog.show();  
    }  

    function stop() {  
        statusDialog.hide();  
    }  
</script>  

您可以通过将命令链接更改为以下内容来应用于您的特定情况:

<p:commandLink id="download" value="Download" ajax="false"
    onclick="PrimeFaces.monitorDownload(showStatus, hideStatus)"
    actionListener="#{zipManager.makeZip()}">

在展示示例中,通过将<p:ajaxStatus>替换为简单的<p:dialog>来实现。
这一切都是通过一个特殊的 cookie 在幕后进行的,JS 会以短时间间隔轮询它(大约每 100 毫秒)。在创建文件下载响应期间,特殊的 cookie 将被设置在其标头上。一旦文件下载响应标头到达浏览器,那么 cookie 就会在浏览器中设置。当 JS 轮询器在浏览器 cookie 空间中找到它时,它就会关闭进度。

请注意,当响应头已到达时,进度将被隐藏。当响应的最后一个字节到达时,它不会被隐藏。无论如何,没有明智的JS方法可以实现这一点。如果创建zip文件比流式传输zip文件更耗时,则可能需要先将其创建到服务器内存或临时磁盘上,然后再从那里进行流式传输。这样,您可以尽可能地推迟响应的提交。 - BalusC
我尝试使用#{zipManager.zip}中完成的作业,但没有成功;(。实际上,zip文件是在服务器内存中创建的。这是耗时的步骤。它比下载本身需要更多的时间。我想在#{zipManager.zip}阶段显示状态。 - kem
你看过我之前的评论吗?毕竟,我觉得你没有理解HTTP的工作原理,并期望在下载完成后对话框会隐藏,这是不可能的。 - BalusC
你听从了我的建议,在服务器内存或临时磁盘上先准备 ZIP 文件,而不是直接将其写入响应中了吗? - BalusC
你是否像展示例子中那样,用<p:dialog>替换了<p:ajaxStatus>? - BalusC
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接