Reputation: 2797
In my application the user is able to push a button to create and download a file. The process takes some time, so I want to block the UI during this process until the download window appears.
The action method were I am handling the response looks basically like this:
public void download() {
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
// set content disposition etc.
XSSFWorkbook wb = getWorkbook();
wb.write(externalContext.getResponseOutputStream());
facesContext.responseComplete();
}
In my JSF view I am triggering a blockUI component to disable the button like this:
<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>
I tried to use the PrimeFaces RequestContext to execute some JavaScript to hide the blockUI component, but that does not work. The JavaScript is not executed:
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();
}
If I am using a ajax call instead of the non-ajax call, then the file download does not work any longer.
Any suggestions how could I archieve my functionality?
Upvotes: 1
Views: 2227
Reputation: 2797
I finally ended up using PrimeFaces 'PrimeFaces.monitorDownload()'
In my view:
<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>
The main trick to get the DownloadMonitor working is to simply set a Cookie in the response:
externalContext.addResponseCookie(
org.primefaces.util.Constants.DOWNLOAD_COOKIE,
"true",
Collections.<String, Object>emptyMap()
);
That way the UI-elements are blocked until the window for the FileDownload appears, which is exactly what I wanted to achieve in the very end.
Upvotes: 4
Reputation: 12337
You should use p:fileDownload
instead of trying to create some homebrewn solution. Modified example from the showcase:
xhtml:
<script type="text/javascript">
function start() {
PF('crBui').show();
}
function stop() {
PF('crBui').hide();
}
</script>
Bean:
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;
}
}
Upvotes: 1