使用PrimeFaces.monitorDownload不会触发JS函数

时间:2013-12-18 16:36:29

标签: jsf jsf-2 primefaces

我正在使用 Primefaces 4.0 进行文件下载。我只想在下载完成时触发JS功能,但似乎无法工作(在Firefox和谷歌浏览器中尝试过)。我的测试用例看起来类似于PF docs中的操作:

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui">
<h:head />

<h:body>
    <script type="text/javascript">
        function startMessage() {
            alert("Download started!");
        }
        function finishMessage() {
            alert("Download finished!");
        }
    </script>
    <h:form>
        <p:commandButton value="Download" ajax="false"
            icon="ui-icon-arrowreturnthick-1-s"
            onclick="PrimeFaces.monitorDownload(startMessage, finishMessage)">
            <p:fileDownload value="#{bean.file}" />
        </p:commandButton>
    </h:form>
</h:body>
</html>
@ManagedBean
@ViewScoped
public class Bean implements Serializable {

    public StreamedContent getFile() {
        return new DefaultStreamedContent(new ByteArrayInputStream(new byte[0]));
    }

}

下载开始时会触发警报,但下载完成后则不会触发警报。其他人可以尝试一下吗?

2 个答案:

答案 0 :(得分:8)

这是一个bug

主要错误在FileDownloadActionListener org.primefaces.component.filedownload包中。

第65行

externalContext.addResponseCookie(Constants.DOWNLOAD_COOKIE, "true", Collections.<String, Object>emptyMap());

Constants.DOWNLOAD_COOKIE是“primefaces.download”,它永远不会随着回复一起发送。

这会导致PrimeFaces.monitorDownload的Interval永远不会调用stop函数,因为cookie永远不会被写入。

答案 1 :(得分:2)

我遇到了同样的问题,发现它与创建的Cookie的 '路径' 属性有关。

我的应用上下文路径的格式为 'http://host/a/b/c' ,因此在服务器中使用 'default'创建Cookie 路径为 '/ a / b / c' ,但在浏览器中我发现在JavaScript执行期间检索到的Cookie只是那些路径 '/ a' (Chrome)或 '/ a /' (Firefox)。因此,即使在创建 'primefaces.download' cookie时,客户端中的JavaScript也没有为应用程序检索它。

我所要做的只是在发送响应之前'覆盖'创建cookie(即创建第二个cookie,浏览器需要正确的路径):

   ...
   FacesContext facesContext = FacesContext.getCurrentInstance();
   ExternalContext externalContext = facesContext.getExternalContext();
   Map<String, Object> map = new HashMap<String, Object>();
   map.put("path", "/a/");
   externalContext.addResponseCookie(Constants.DOWNLOAD_COOKIE, "true", map);
   ...

此外,我注意到 PrimeFaces.monitorDownload() 的默认实施尝试'清理' 'primefaces.download' Cookie只需将其值设置为'null',但由于Chrome和Firefox处理Cookie的方式不同(添加最后的'/'字符到Firefox中的当前路径)我最好还'覆盖'也是执行结束函数时清理cookie的JS代码:

   ...    
   document.cookie = 'primefaces.download=; path=/a/; expires=Thu, 01 Jan 1970 00:00:00 UTC';
   ...

这样我确保在下一次执行中,cookie在客户端中根本不存在,直到它再次在服务器中创建。