2016-04-27 182 views
0

我有多模塊maven項目,有一個請求生成過程,在這個過程中有一些上傳組件的vaadin在這些我們上傳一些文件,必須只有png,jpgs ,pdf和bmp。 現在,在這個過程的最後,我將所有文檔類型合併爲一個pdf,然後用文件下載器下載。PDF與itext和pdfbox合併

我在一個按鈕單擊事件調用該函數是:

/** 
    * This function is responsible for getting 
    * all documents from request and merge 
    * them in a single pdf file for 
    * download purposes 
    * @throws Exception 
    */ 
    protected void downloadMergedDocument() throws Exception { 

    // Calling create pdf function for merged pdf 
    createPDF(); 

    // Setting the merged file as a resource for file downloader 
    Resource myResource = new FileResource(new File (mergedReportPath +request.getWebProtocol()+ ".pdf")); 
    FileDownloader fileDownloader = new FileDownloader(myResource); 

    // Extending the download button for download 
    fileDownloader.extend(downloadButton); 

} 

/** 
* This function is responsible for providing 
* the PDF related to a particular request that 
* contains all the documents merged inside it 
* @throws Exception 
*/ 
private void createPDF() throws Exception { 
    try{ 
     // Getting the current request 
     request = evaluationRequestUI.getRequest(); 

     // Fetching all documents of the request    
     Collection<DocumentBean> docCollection = request.getDocuments(); 

     // Initializing Document of using itext library 
     Document doc = new Document(); 

     // Setting PdfWriter for getting the merged images file 
     PdfWriter.getInstance(doc, new FileOutputStream(mergedReportPath+ "/mergedImages_" + request.getWebProtocol()+ ".pdf")); 

     // Opening document 
     l_doc.open(); 

     /** 
     * Here iterating on document collection for the images type 
     * document for merging them into one pdf  
     */           
     for (DocumentBean documentBean : docCollection) { 
      byte[] documents = documentBean.getByteArray(); 

      if(documentBean.getFilename().toLowerCase().contains("png") || 
        documentBean.getFilename().toLowerCase().contains("jpeg") || 
        documentBean.getFilename().toLowerCase().contains("jpg") || 
        documentBean.getFilename().toLowerCase().contains("bmp")){ 

       Image img = Image.getInstance(documents); 

       doc.setPageSize(img); 
       doc.newPage(); 
       img.setAbsolutePosition(0, 0); 
       doc.add(img); 
      } 
     } 

     // Closing the document 
     doc.close(); 

     /** 
     * Here we get all the images type documents merged into 
     * one pdf, now moving to pdfbox for searching the pdf related 
     * document types in the request and merging the above resultant  
     * pdf and the pdf document in the request into one pdf 
     */ 

     PDFMergerUtility utility = new PDFMergerUtility(); 

     // Adding the above resultant pdf as a source 
     utility.addSource(new File(mergedReportPath+ "/mergedImages_" + request.getWebProtocol()+ ".pdf")); 

     // Iterating for the pdf document types in the collection 
     for (DocumentBean documentBean : docCollection) { 
      byte[] documents = documentBean.getByteArray(); 

      if(documentBean.getFilename().toLowerCase().contains("pdf")){ 
       utility.addSource(new ByteArrayInputStream(documents)); 
      } 
     } 

     // Here setting the final pdf name 
     utility.setDestinationFileName(mergedReportPath +request.getWebProtocol()+ ".pdf"); 

     // Here final merging and then result 
     utility.mergeDocuments(); 

    }catch(Exception e){ 
     m_logger.error("CATCH", e); 
     throw e; 
    } 
} 

注:mergedReportPath要保存PDF文件中定義的路徑,然後
從那裏retreive下載的目的。

現在,我已經在這兩個問題:

  1. 當我的第一個要求做這個過程中,它給我的 目標文件夾中的PDF文件,但它不下載。
  2. 當我再次爲第二個請求執行此過程時,它會卡住 utility.mergedocuments(),我的意思是如果它發現pdf已經在目標文件夾中存在 卡住了。我不知道 問題在哪裏。請幫助
+0

爲什麼在創建文件時,目的是要將其發送到瀏覽器?你爲什麼不在內存中創建它,然後通過響應對象發送字節? –

+0

你能告訴我鋤頭這樣做這個itext或pdfbox –

回答

0

在你的問題的評論部分,你已經明確了你不需要磁盤上的文件,但是你想發送PDF到瀏覽器。你想知道如何做到這一點。這是官方文檔中解釋說:How can I serve a PDF to a browser without storing a file on the server side?

這是你如何在內存中創建一個PDF:

// step 1 
Document document = new Document(); 
// step 2 
ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
PdfWriter.getInstance(document, baos); 
// step 3 
document.open(); 
// step 4 
document.add(new Paragraph("Hello")); 
// step 5 
document.close(); 

合併PDF文件與PdfCopy完成:How to merge documents correctly? 您需要採用同樣的原則與上述那些示例:用ByteArrayOutputStream代替FileOutputStream

現在您有PDF字節存儲在baos對象中。我們可以將它發送到瀏覽器這樣的:

// setting some response headers 
response.setHeader("Expires", "0"); 
response.setHeader("Cache-Control", 
    "must-revalidate, post-check=0, pre-check=0"); 
response.setHeader("Pragma", "public"); 
// setting the content type 
response.setContentType("application/pdf"); 
// the contentlength 
response.setContentLength(baos.size()); 
// write ByteArrayOutputStream to the ServletOutputStream 
OutputStream os = response.getOutputStream(); 
baos.writeTo(os); 
os.flush(); 
os.close(); 

請務必閱讀documentation如果您還有其他問題。

+0

對不起,對於答覆已晚,布魯諾答案thanx,它的工作,只有一個問題,你可以告訴我。我如何在這裏爲最終的PDF設置名稱。我想將它設置爲像request.getfilename()這樣的名稱,在那裏爲下載的文件名設置類似的內容,現在它給了我一些目錄名 –

+0

要設置PDF的名稱,您必須設置標題「Content-Disposition」。 –

1

在2.0版本的PDFBox中,您可以使用setDestinationStream()來設置輸出流。因此,您只需致電

response.setContentType("application/pdf"); 
OutputStream os = response.getOutputStream(); 
utility.setDestinationStream(os); 
utility.mergeDocuments(); 
os.flush(); 
os.close(); 

您不能以這種方式設置響應大小;如果必須,請使用ByteArrayOutputStream,如Bruno的答案或this one