2011-05-07 187 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();  
      }