Search code examples
javaitext

How can I merge the documents consisting PDFs as well as images?


In my current code I am merging the documents consisting PDF files.

public static void appApplicantDownload(File file) {

 Connection con = getConnection();
 Scanner sc = new Scanner(System.in);
 List < InputStream > list = new ArrayList < InputStream > ();
 try {
  OutputStream fOriginal = new FileOutputStream(file, true); // original

  list.add(new FileInputStream(file1));
  list.add(new FileInputStream(file2));
  list.add(new FileInputStream(file3));
  doMerge(list, fOriginal);

 } catch (Exception e) {

 }
}




public static void doMerge(List < InputStream > list, OutputStream outputStream) throws DocumentException, IOException {
 try {
  System.out.println("Merging...");
  Document document = new Document();
  PdfCopy copy = new PdfCopy(document, outputStream);
  document.open();

  for (InputStream in : list) {
   ByteArrayOutputStream b = new ByteArrayOutputStream();
   IOUtils.copy( in , b);
   PdfReader reader = new PdfReader(b.toByteArray());

   for (int i = 1; i <= reader.getNumberOfPages(); i++) {
    copy.addPage(copy.getImportedPage(reader, i));
   }
  }

  outputStream.flush();
  document.close();
  outputStream.close();
 } catch (Exception e) {
  e.printStackTrace();
 }
}

But now I want to change the code such that it should allow Image as well as PDFs to be merged. Above code is giving me the error that No PDF Signature found


Solution

  • First, you have to know somehow if the file is a PDF or an image. The easiest way would be to use the extension of the file. So you would have get extension of the file and then pass this information to your doMerge method. Do achieve that, I would change your current method

    public static void doMerge(List<InputStream> list, OutputStream outputStream)
    

    For something like

    public static void doMerge(Map<InputStream, String> files, OutputStream outputStream)
    

    So each InputStream is associated with a extension.

    Second, you have to load images and pdf seperately. So your loop should look like

    for (InputStream in : files.keySet()) {
        String ext = files.get(in);
    
        if(ext.equalsIgnoreCase("pdf"))
        {
            //load pdf here
        }
        else if(ext.equalsIgnoreCase("png") || ext.equalsIgnoreCase("jpg"))
        {
            //load image here
        }
    }
    

    In java, you can easily load an Image using ImageIO. Look at this question for more details on this topic: Load image from a filepath via BufferedImage

    Then to add your image into the PDF, use the PdfWriter

    PdfWriter pw = PdfWriter.GetInstance(doc, outputStream);
    Image img = Image.GetInstance(inputStream);
    doc.Add(img);
    doc.NewPage();
    

    If you want to convert your image into PDF before and merge after you also can do that but you just have to use the PdfWriter to write them all first.