Blank pages when creating and downloading a PDF file (iText & JSF)
I'm having a problem when I try to create a PDF file using iText and want to download it immediately afterwards. First I create a PDF file using the iText library, the file is written to a TEMP folder on the server, this all works fine. But afterwards I call a download screen for downloading the PDF file from the TEMP folder to the client, and here something goes wrong. The download screen shows a Firefox (browser) icon instead of the Acrobat icon. When I donwload the file I only get to see blank PDF pages, but the number of pages is correct. E.g. I have a PDF file of 4 pages, I get 4 blank pages as a result, there is no content. The PDF file in the TEMP folder however is correct, it has got 4 pages with the correct content.
This is my java code, it is executed when the user clicks a h:commandLink
public <E> String createPDF(E type, boolean print) throws Exception {
Document document = new Document();
// create a File name for the document
getPdfNaam(type);
try {
//create a PDF writer
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(TEMP + naam + ".pdf"));
//open the PDF document
document.open();
} catch (Exception e) {
e.printStackTrace();
}
//build the PDF file using iText
buildPDFContent(document, type);
//close the PDF document
close(document);
String downloadFi开发者_开发知识库le = TEMP + naam + ".pdf";
//call Servlet for download screen in the browser
ServletContext context = (ServletContext) ContextProvider.getFacesContext().getExternalContext().getContext();
HttpServletResponse response = (HttpServletResponse) ContextProvider.getFacesContext().getExternalContext().getResponse();
response.setContentType("application/force-download");
downloadFile = TEMP + naam + ".pdf";
byte[] buf = new byte[1024];
try {
File file = new File(downloadFile);
long length = file.length();
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
ServletOutputStream out = response.getOutputStream();
response.setContentLength((int) length);
while ((in != null) && ((length = in.read(buf)) != -1)) {
out.write(buf, 0, (int) length);
}
in.close();
out.close();
} catch (Exception exc) {
exc.printStackTrace();
}
response.addHeader("Content-Disposition", "attachment; filename=\"" + naam + ".pdf" + "\"");
return null;
}
I found the code for calling a download screen on this website http://www.winstonprakash.com/articles/jsf/file_download_link.htm I searched on Google and Stack Overflow, but I couldn't find any related questions. I'm using JSF 2.0 Any help would be greatly appreciated!
The content type should be set to application/pdf
and the content disposition header should be set before any byte is been written to the response, otherwise it's too late to set it. Plus, you can also just write the PDF to the outputstream of the response immediately.
All with all, the method can be simplified as follows:
public <E> String createPDF(E type, boolean print) throws Exception {
getPdfNaam(type); // ??? It should *return* name, not change/set the local value.
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
ec.setResponseHeader("Content-Type", "application/pdf");
ec.setResponseHeader("Content-Disposition", "attachment; filename=\"" + naam + ".pdf" + "\"");
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, ec.getResponseOutputStream());
document.open();
buildPDFContent(document, type);
close(document);
}
Also ensure that you're calling FacesContext#responseComplete()
to signal JSF that you've already taken the response handling in your hands so that it knows that it doesn't need to navigate to some view.
FacesContext.getCurrentInstance().responseComplete();
you can you the outputstream to response immediately. The below is my code:
OutputStream out = response.getOutputStream();
response.setContentType("application/x-msdownload;charset=utf-8");
response.setHeader("Content-Disposition", "attachment;"+"filename="+System.currentTimeMillis()+".pdf");
Document document = new Document(PageSize.A4, 10, 10, 10,10);
PdfWriter.getInstance(document, out);
document.open();
//The below is document add data
//....
//close flow
if(document!=null){
document.close();
}
if(out!=null){
out.flush();
out.close();
}
精彩评论