2011-05-07 170 views
2

我在尝试使用iText创建PDF文件并希望在此后立即下载时出现问题。首先,我使用iText库创建PDF文件,将文件写入服务器上的TEMP文件夹,这一切都正常。但之后,我打电话给下载屏幕,将TEMP文件夹中的PDF文件下载到客户端,这里出现了问题。下载屏幕显示的是Firefox(浏览器)图标,而不是Acrobat图标。当我卸载文件时,我只能看到空白的PDF页面,但页面数量正确。例如。我有一个4页的PDF文件,结果我得到4个空白页,没有内容。然而,TEMP文件夹中的PDF文件是正确的,它有4页正确的内容。创建和下载PDF文件时出现空白页(iText&JSF)

这是我的Java代码,它是当用户点击啊执行: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 我搜索谷歌和堆栈溢出,但我找不到任何相关的问题。我正在使用JSF 2.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(); 
+0

编译器指出它无法“查找”该方法。 setResponseHeader(String,String)感谢您使用outputstream的提示,更少的代码。 :) – Bart1990 2011-05-09 17:18:23

+0

然后,你*实际*不使用JSF 2.0,如问题中所示。它是在JSF 2.0中引入的。另请参阅http://download.oracle.com/javaee/6/api/javax/faces/context/ExternalContext.html#setResponseHeader%28java.lang.String,%20java.lang.String%29 – BalusC 2011-05-09 17:32:00

+0

嗯,你是对的,尽管netbeans中我的项目属性表明我正在使用JSF 2.0库。我要检查一下并保持发布。 – Bart1990 2011-05-09 20:53:21

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();  
      }