jsf 2 - How to provide a file download from a JSF backing bean?
Is there any way of providing a file download from a JSF backing bean action method?
I have tried a lot of things. Main problem is that I cannot figure how to get theOutputStream
of the response in order to write the file content to. I know how to do it with aServlet
, but this cannot be invoked from a JSF form and requires a new request.
How can I get theOutputStream
of the response from the currentFacesContext
?
Answer
Solution:
Introduction
You can get everything through
. In JSF 1.x, you can get the raw
HttpServletResponse
object by. In JSF 2.x, you can use the bunch of new delegate methods like
without the need to grab the
HttpServletResponse
from under the JSF hoods.On the response, you should set the
Content-Type
header so that the client knows which application to associate with the provided file. And, you should set theContent-Length
header so that the client can calculate the download progress, otherwise it will be unknown. And, you should set theContent-Disposition
header toattachment
if you want a Save As dialog, otherwise the client will attempt to display it inline. Finally just write the file content to the response output stream.Most important part is to call
to inform JSF that it should not perform navigation and rendering after you've written the file to the response, otherwise the end of the response will be polluted with the HTML content of the page, or in older JSF versions, you will get an
IllegalStateException
with a message likegetoutputstream() has already been called for this response
when the JSF implementation callsgetWriter()
to render HTML.Turn off ajax / don't use remote command!
You only need to make sure that the action method is not called by an ajax request, but that it is called by a normal request as you fire with
<h:commandLink>
and<h:commandButton>
. Ajax requests and remote commands are handled by JavaScript which in turn has, due to security reasons, no facilities to force a Save As dialogue with the content of the ajax response.In case you're using e.g. PrimeFaces
<p:commandXxx>
, then you need to make sure that you explicitly turn off ajax viaajax="false"
attribute. In case you're using ICEfaces, then you need to nest a<f:ajax disabled />
in the command component.Generic JSF 2.x example
Generic JSF 1.x example
Common static file example
In case you need to stream a static file from the local disk file system, substitute the code as below:
Common dynamic file example
In case you need to stream a dynamically generated file, such as PDF or XLS, then simply provide
output
there where the API being used expects anOutputStream
.E.g. iText PDF:
E.g. Apache POI HSSF:
Note that you cannot set the content length here. So you need to remove the line to set response content length. This is technically no problem, the only disadvantage is that the enduser will be presented an unknown download progress. In case this is important, then you really need to write to a local (temporary) file first and then provide it as shown in previous chapter.
Utility method
If you're using JSF utility library OmniFaces, then you can use one of the three convenient
methods taking either a
File
, or anInputStream
, or abyte[]
, and specifying whether the file should be downloaded as an attachment (true
) or inline (false
).Yes, this code is complete as-is. You don't need to invoke
responseComplete()
and so on yourself. This method also properly deals with IE-specific headers and UTF-8 filenames. You can find source code here.Answer
Solution:
Answer
Solution:
This is what worked for me:
Answer
Solution:
This is my solution, an extension of BalusC's answer
Answer
Solution:
here is the complete code snippet http://bharatonjava.wordpress.com/2013/02/01/downloading-file-in-jsf-2/
You may change the file reading logic in case you want file to get generated at runtime.