当我尝试使用iText创建PDF文件并希望之后立即下载时,我遇到了问题。首先我使用iText库创建一个PDF文件,该文件被写入服务器上的TEMP文件夹,这一切都正常。但之后我打电话给下载屏幕,将PDF文件从TEMP文件夹下载到客户端,这里出了点问题。下载屏幕显示Firefox(浏览器)图标而不是Acrobat图标。当我下载文件时,我只能看到空白的PDF页面,但页面数量是正确的。例如。我有一个4页的PDF文件,因此我得到4个空白页,没有内容。但TEMP文件夹中的PDF文件是正确的,它有4页,内容正确。
这是我的java代码,它在用户单击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 downloadFile = 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;
}
我找到了在此网站上调用下载屏幕的代码http://www.winstonprakash.com/articles/jsf/file_download_link.htm 我搜索了Google和Stack Overflow,但我找不到任何相关问题。我正在使用JSF 2.0任何帮助将不胜感激!
答案 0 :(得分:3)
内容类型应设置为application/pdf
,并且在将任何字节写入响应之前应设置内容处置标头,否则设置它为时已晚。另外,您还可以立即将PDF写入响应的输出流。
总而言之,该方法可以简化如下:
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);
}
同时确保您正在调用FacesContext#responseComplete()
向JSF发出信号,告知您已经掌握了响应处理,以便它知道它不需要导航到某个视图。
FacesContext.getCurrentInstance().responseComplete();
答案 1 :(得分:0)
你可以让输出流立即响应。以下是我的代码:
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();
}