JS function not triggered with PrimeFaces.monitorDownload

百般思念 提交于 2019-12-18 06:48:45

问题


I'm working in file downloading with Primefaces 4.0. I just want to trigger a JS function when download completes, but seems not to work (tried in Firefox and Google Chrome). My test case looks similar to what's done in the 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]));
    }

}

The alert is triggered when download starts, but not when download finishes. Could anyone else give it a try?


回答1:


it's a bug.

The main bug is in FileDownloadActionListener of org.primefaces.component.filedownload package.

Line 65

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

The Constants.DOWNLOAD_COOKIE is "primefaces.download", and it's never sent with the response.

That would cause PrimeFaces.monitorDownload's Interval to never call the stop function, since the cookie is never written.




回答2:


I had the same problem and found it was related to the 'path' attribute of the cookie created.

My app context path has the form 'http://host/a/b/c', hence in the server the cookie is created with 'default' path as '/a/b/c', but in the browser I found the cookies retrieved during the JavaScript execution were only the ones with path '/a' (Chrome) or '/a/' (Firefox). So even when the 'primefaces.download' cookie was being created, the JavaScript in the client was not retrieving it for the application.

All I had to do was to 'override' the cookie creation before the response is sent (i.e. create a second cookie with correct path expected by the browser):

   ...
   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);
   ...

Also, I noticed the default implementation of PrimeFaces.monitorDownload() tries to 'clean' the 'primefaces.download' cookie by just setting its value to 'null', but since there is difference in how Chrome and Firefox handle cookies (appending a last '/' character to the current path in Firefox) I better did 'override' also the JS code to clean the cookie once the ending function is executed:

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

That way I make sure that in the next execution the cookie won't yet be there at all in the client until it again gets created in the server.



来源:https://stackoverflow.com/questions/20663551/js-function-not-triggered-with-primefaces-monitordownload

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!