Sending Files (like PDF) to the Browser

Introduction

If you need the user to be able to download a file that is stored somewhere in the server you may face some problems, like the file getting printed into the content of the page, etc. So the idea is to send the file to the Response, setting the right headers, then the user will be presented with a Open/save dialog for him/her to take the required action.

How to do it

You have to bind an action in the JSP to a method in your backing bean.

The content of the method could be like this:

//We must get first our context
FacesContext context = FacesContext.getCurrentInstance();
//Then we have to get the Response where to write our file
HttpServletResponse response =
( HttpServletResponse ) context.getExternalContext().getResponse();
//Now we create some variables we will use for writting the file to the response
String filePath = null;
int read = 0;
byte[] bytes = new byte[1024];
//Be sure to retrieve the absolute path to the file with the required method
filePath = pathToTheFile;
//Now set the content type for our response, be sure to use the best suitable content type depending on your file
//the content type presented here is ok for, lets say, text files and others (like CSVs, PDFs)
response.setContentType("application/pdf");
//This is another important attribute for the header of the response
//Here fileName, is a String with the name that you will suggest as a name to save as
//I use the same name as it is stored in the file system of the server.
response.setHeader("Content-Disposition", "attachment;filename=\"" +
fileName + "\"");
//Streams we will use to read, write the file bytes to our response
FileInputStream fis = null;
OutputStream os = null;
//First we load the file in our InputStream
fis = new FileInputStream(new File(filePath,fileName));
os = response.getOutputStream();
//While there are still bytes in the file, read them and write them to our OutputStream
while((read = fis.read(bytes)) != -1){
os.write(bytes,0,read);
}
//Clean resources
os.flush();
os.close();
//This option isn't quite necessary, It worked for me with or without it
FacesContext.getCurrentInstance().responseComplete();
//End of the method