2016-04-27 177 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