tushar sharma
tushar sharma

Reputation: 105

PDF merging with itext and pdfbox

I have multi module maven project, in that there is a process of request generation and in this process there are some upload component of vaadin in these we are uploading some documents that must be only png, jpgs, pdf and bmp. Now at last of this process i am merging all the document types into one pdf and then downloading it with file downloader.

The function i am calling on a button click event is:

   /**
     * 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;
    }
}  

Note: mergedReportPath is a path defined for pdf files to be stored and then
retreive from there for download purposes.

Now, i have two problems in that:

  1. When i do this process for a first request , it give me the pdfs in the destination folder but it does not download it.
  2. When i again do the this process for the second request, it get stuck on the utility.mergedocuments(), i mean if it found that the pdf is already present in the destination folder it get stuck. I dont know where the problem is. Please Help

Upvotes: 0

Views: 2258

Answers (2)

Tilman Hausherr
Tilman Hausherr

Reputation: 18851

In the 2.0 version of PDFBox, you can set an output stream with setDestinationStream(). Thus, you just call

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

You can't set the response size this way; if you have to, use ByteArrayOutputStream like in Bruno's answer or this one.

Upvotes: 2

Bruno Lowagie
Bruno Lowagie

Reputation: 77528

In the comment section of your question, you have clarified that you don't need the file on disk, but that you want to send the PDF to the browser. You want to know how to achieve this. This is explained in the official documentation: How can I serve a PDF to a browser without storing a file on the server side?

This is how you create a PDF in memory:

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

Merging PDFs is done with PdfCopy: How to merge documents correctly? You need to apply the same principle as above to those examples: replace the FileOutputStream by a ByteArrayOutputStream.

Now you have PDF bytes that are stored in the baos object. We can send it to the browser like this:

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

Make sure to read the documentation if you have further questions.

Upvotes: 0

Related Questions