PDF与itext和pdfbox合并

时间:2016-04-27 05:17:53

标签: java hibernate itext pdfbox vaadin7

我有多模块maven项目,因为有一个请求生成过程,在这个过程中有一些vaadin的上传组件,我们正在上传一些必须只有png,jpgs,pdf和bmp的文件。 现在,在这个过程的最后,我将所有文档类型合并为一个pdf,然后使用文件下载程序下载。

我在按钮点击事件上调用的功能是:

   /**
     * 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文件定义的路径,然后是
      从那里撤退以供下载。

现在,我有两个问题:

  1. 当我为第一个请求执行此过程时,它会给我pdf 目标文件夹但不下载它。
  2. 当我再次为第二个请求执行此过程时,它会被卡住 utility.mergedocuments(),我的意思是如果它发现pdf已经存在 出现在目标文件夹中它会卡住。我不知道在哪里 问题是。请帮助

2 个答案:

答案 0 :(得分:2)

在PDF版的2.0版中,您可以使用setDestinationStream()设置输出流。因此,您只需致电

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

您不能以这种方式设置响应大小;如果必须,请使用布鲁诺答案中的ByteArrayOutputStreamthis one

答案 1 :(得分:0)

在您的问题的评论部分,您已澄清您不需要磁盘上的文件,但您想要将PDF发送到浏览器。你想知道如何实现这一目标。官方文档中解释了这一点:How can I serve a PDF to a browser without storing a file on the server side?

这是在内存中创建PDF的方法:

#include <dlfcn.h>

extern "C" typedef void (*hello_t)( const char* text );

int main() {
  void* lib = dlopen("./libhello.so", RTLD_LAZY);
  hello_t hello = (hello_t)dlsym( lib, "hello" );

  hello("World!");

  dlclose(lib);
}

使用// 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:How to merge documents correctly? 您需要对上述示例应用与上述相同的原则:将PdfCopy替换为FileOutputStream

现在您拥有存储在ByteArrayOutputStream对象中的PDF字节。我们可以像这样将它发送到浏览器:

baos

如果您有其他问题,请务必阅读documentation