在非 ajax 调用中的客户端执行 JavaScript

Execute JavaScript on client side within an non ajax call

本文关键字:客户端 执行 JavaScript ajax 调用 在非      更新时间:2023-09-26

在我的应用程序中,用户可以按下按钮来创建和下载文件。该过程需要一些时间,因此我想在此过程中阻止 UI,直到出现下载窗口。

我正在处理响应的操作方法基本上如下所示:

public void download() {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    ExternalContext externalContext = facesContext.getExternalContext();
    // set content disposition etc.    
    XSSFWorkbook wb = getWorkbook();
    wb.write(externalContext.getResponseOutputStream());            
    facesContext.responseComplete();
}

在我的 JSF 视图中,我正在触发一个 blockUI 组件来禁用按钮,如下所示:

<p:commandButton value="Doanload" id="b" 
                 action="#{bean.doanload()}"
                 ajax="false" 
                 onclick="PF('crBui').show();"  />
<p:blockUI block=":trGrid" widgetVar="crBui" trigger="b">
     <p:graphicImage value="/images/loading.gif" alt="loading..."/>
</p:blockUI>

我尝试使用 PrimeFaces RequestContext 来执行一些 JavaScript 来隐藏 blockUI 组件,但这不起作用。JavaScript 不会执行:

    public void download() {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        ExternalContext externalContext = facesContext.getExternalContext();
        // set content disposition etc.    
        XSSFWorkbook wb = getWorkbook();
        wb.write(externalContext.getResponseOutputStream());    
        RequestContext.getCurrentInstance()
                      .execute("PF('crBui').hide();");        
        facesContext.responseComplete();
    }
如果我使用 ajax 调用

而不是非 ajax 调用,则文件下载不再有效。

任何建议如何归档我的功能?

我最终使用了PrimeFaces 'PrimeFaces.monitorDownload()'

在我看来:

<p:commandButton value="Doanload" id="b" 
             action="#{bean.doanload()}"
             ajax="false" 
             onclick="PrimeFaces.monitorDownload(start, stop);"  />
<script type="text/javascript">
    function start() {
        PF('crBui').show();
    }
    function stop() {
        PF('crBui').hide();
    }
</script>

让下载监视器工作的主要技巧是简单地在响应中设置一个 Cookie:

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

这样,UI元素将被阻止,直到出现FileDownload的窗口,这正是我最终想要实现的目标。

您应该使用p:fileDownload而不是尝试创建一些自制解决方案。从展示中修改的示例:

.xhtml:

<script type="text/javascript">
function start() {
    PF('crBui').show();
}
function stop() {
    PF('crBui').hide();
}
</script>

豆:

import java.io.InputStream;
import javax.faces.bean.ManagedBean;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;
@ManagedBean
public class FileDownloadView {
    private StreamedContent file;
    public FileDownloadView() {       
        InputStream stream = <create your stream>
        file = new DefaultStreamedContent(stream, "<your mime-type>", "<your filename>");
    }
    public StreamedContent getFile() {
        return file;
    }
}