which is the right way to download a file using JSF?, just putting a link to the file ?? in that case how do i get the file URL??
i have seen one example using BufferedInputStream:
http://www.winstonprakash.com/articles/jsf/file_download_link.htm
What are the differences?
Thanks
If it's a simple file, just place in public webcontent (there where you put your static and JSF files) and create a link.
<h:outputLink value="/files/file.ext">link</h:outputLink>
The servletcontainer will worry about applying the correct headers.
If it's located outside the public webcontent for some specific reasons (e.g. in a fixed path at server machine, or in a database), then create a servlet which gets an InputStream
of it and writes it to the OutputStream
of the response along at least the Content-Type
, Content-Disposition
and Content-Length
headers. You can find here a simple kickoff example. Also that can simply be linked on the servlet's url-pattern
.
If it's to be dynamically generated and depending on the JSF specific request parameters, then you can also do so in a managed bean action which is bound by h:commandLink
or h:commandButton
, but you only need to ensure that you call FacesContext#responseComplete()
at end of bean's action method to prevent JSF from taking the navigation in hands. The same kind of servlet code can be reused to stream the file. You can find a kickoff example in this answer.
I needed to make a similar code to download a file via JSF
That's my download button in my JSF page
<h:commandButton value="Download" action="#{helloBean.downloadFile}" />
And it's my Java Code
public void downloadFile() {
File file = new File("/home/marco/file.txt");
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
response.setHeader("Content-Disposition", "attachment;filename=file.txt");
response.setContentLength((int) file.length());
ServletOutputStream out = null;
try {
FileInputStream input = new FileInputStream(file);
byte[] buffer = new byte[1024];
out = response.getOutputStream();
int i = 0;
while ((i = input.read(buffer)) != -1) {
out.write(buffer);
out.flush();
}
FacesContext.getCurrentInstance().getResponseComplete();
} catch (IOException err) {
err.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException err) {
err.printStackTrace();
}
}
}
I have had an error on
FacesContext.getCurrentInstance().getResponseComplete();
from the type
java.lang.IllegalStateException: getOutputStream() has already been called for this response
and i solved it:
JSF page:
<h:commandButton action="#{bean.downloadFile}" id="downloadBtn" value="Download"/>
Bean method:
public void downloadFile(File file) {
FacesContext facesContext = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
response.setHeader("Content-Disposition", "attachment;filename=file.txt");
response.setContentLength((int) file.length());
FileInputStream input= null;
try {
int i= 0;
input = new FileInputStream(file);
byte[] buffer = new byte[1024];
while ((i = input.read(buffer)) != -1) {
response.getOutputStream().write(buffer);
response.getOutputStream().flush();
}
facesContext.responseComplete();
facesContext.renderResponse();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(input != null) {
input.close();
}
} catch(IOException e) {
e.printStackTrace();
}
}
}
精彩评论