¿Cómo fusionar dos archivos PDF en uno en Java?

6 minutos de lectura

¿Cómo fusionar dos archivos PDF en uno en Java?
lípidos

Quiero fusionar muchos archivos PDF en uno usando PDFBox y esto es lo que he hecho:

PDDocument document = new PDDocument();
for (String pdfFile: pdfFiles) {
    PDDocument part = PDDocument.load(pdfFile);
    List<PDPage> list = part.getDocumentCatalog().getAllPages();
    for (PDPage page: list) {
        document.addPage(page);
    }
    part.close();
}
document.save("merged.pdf");
document.close();

Donde pdfFiles es un ArrayList<String> que contiene todos los archivos PDF.

Cuando ejecuto lo anterior, siempre obtengo:

org.apache.pdfbox.exceptions.COSVisitorException: Bad file descriptor

¿Estoy haciendo algo mal? ¿Hay alguna otra forma de hacerlo?

¿Cómo fusionar dos archivos PDF en uno en Java?
queruvim

¿Por qué no usar el PDFMergerUtility de pdfbox?

PDFMergerUtility ut = new PDFMergerUtility();
ut.addSource(...);
ut.addSource(...);
ut.addSource(...);
ut.setDestinationFileName(...);
ut.mergeDocuments();

  • También funciona, pero también estaba usando PDFBox para crear PDF.

    – Lipis

    02 feb.

  • ¿Permitirá fusionar un PDF que tiene imágenes escaneadas y un PDF que fue escrito?

    – Ragesh Kr

    03 mar.

  • @RageshKr: según tengo entendido, fusionará cualquier PDF independientemente de su contenido.

    – queruvim

    03 mar. 15 a las 13:48

  • ¿Hay alguna forma de mencionar el número de página en cada página para el pdf resultante?

    – Prateek Singh

    31 ago. 17 a las 5:24

  • ¿Se puede usar si los archivos pdf tienen contraseñas?

    – codificador

    08 jun.

¿Cómo fusionar dos archivos PDF en uno en Java?
Michael Lloyd Lee mlk

Una búsqueda rápida en Google devolvió este error: “Descriptor de archivo incorrecto al guardar un documento con archivos PDF importados”.

Parece que debe mantener abiertos los archivos PDF que se fusionarán hasta que haya guardado y cerrado el PDF combinado.

  • A pesar de que la publicación tenía dos años, esto resolvió el problema. ¡Tienes que mantenerlos abiertos!

    – Lipis

    27 ago. 10 en 15:28

Este es un código listo para usar, fusionando cuatro archivos pdf con itext.jar de http://central.maven.org/maven2/com/itextpdf/itextpdf/5.5.0/itextpdf-5.5.0.jar, más en http://tutorialspointexamples.com/

import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;

/**
 * This class is used to merge two or more 
 * existing pdf file using iText jar.
 */
public class PDFMerger {

static void mergePdfFiles(List<InputStream> inputPdfList,
        OutputStream outputStream) throws Exception{
    //Create document and pdfReader objects.
    Document document = new Document();
    List<PdfReader> readers = 
            new ArrayList<PdfReader>();
    int totalPages = 0;

    //Create pdf Iterator object using inputPdfList.
    Iterator<InputStream> pdfIterator = 
            inputPdfList.iterator();

    // Create reader list for the input pdf files.
    while (pdfIterator.hasNext()) {
            InputStream pdf = pdfIterator.next();
            PdfReader pdfReader = new PdfReader(pdf);
            readers.add(pdfReader);
            totalPages = totalPages + pdfReader.getNumberOfPages();
    }

    // Create writer for the outputStream
    PdfWriter writer = PdfWriter.getInstance(document, outputStream);

    //Open document.
    document.open();

    //Contain the pdf data.
    PdfContentByte pageContentByte = writer.getDirectContent();

    PdfImportedPage pdfImportedPage;
    int currentPdfReaderPage = 1;
    Iterator<PdfReader> iteratorPDFReader = readers.iterator();

    // Iterate and process the reader list.
    while (iteratorPDFReader.hasNext()) {
            PdfReader pdfReader = iteratorPDFReader.next();
            //Create page and add content.
            while (currentPdfReaderPage <= pdfReader.getNumberOfPages()) {
                  document.newPage();
                  pdfImportedPage = writer.getImportedPage(
                          pdfReader,currentPdfReaderPage);
                  pageContentByte.addTemplate(pdfImportedPage, 0, 0);
                  currentPdfReaderPage++;
            }
            currentPdfReaderPage = 1;
    }

    //Close document and outputStream.
    outputStream.flush();
    document.close();
    outputStream.close();

    System.out.println("Pdf files merged successfully.");
}

public static void main(String args[]){
    try {
        //Prepare input pdf file list as list of input stream.
        List<InputStream> inputPdfList = new ArrayList<InputStream>();
        inputPdfList.add(new FileInputStream("..\pdf\pdf_1.pdf"));
        inputPdfList.add(new FileInputStream("..\pdf\pdf_2.pdf"));
        inputPdfList.add(new FileInputStream("..\pdf\pdf_3.pdf"));
        inputPdfList.add(new FileInputStream("..\pdf\pdf_4.pdf"));


        //Prepare output stream for merged pdf file.
        OutputStream outputStream = 
                new FileOutputStream("..\pdf\MergeFile_1234.pdf");

        //call method to merge pdf files.
        mergePdfFiles(inputPdfList, outputStream);     
    } catch (Exception e) {
        e.printStackTrace();
    }
    }
}

  • La pregunta claramente está etiquetada como pdfbox. Presentas una solución para itext. Por lo tanto, su respuesta está fuera de tema. (Dicho esto, su solución de iText también es mala y los desarrolladores de iText generalmente la desaconsejan, ya que descarta funciones interactivas e ignora la rotación y el tamaño de las páginas).

    – mkl

    09 ene.

  • Entonces el título debería ser “Cómo fusionar dos archivos PDF en uno en Java con PdfBox”

    – Lluís Martínez

    11 dic. 17 en 11:35

  • Además, iText viene con una licencia desagradable.

    – Daniel Bo

    16 ene.

  • Este ejemplo se llama IncorrectExample porque no es así como normalmente resolvería el problema de rotar páginas, ni de fusionar documentos. La forma correcta NO es usar Document / PdfWriter, sino usar PdfStamper, PdfCopy o PdfSmartCopy. Sin embargo: en la pregunta mencionada anteriormente, las circunstancias son muy particulares y usar este ejemplo en esas circunstancias está justificado: developers.itextpdf.com/examples/merging-pdf-documents-itext5/…

    – victorpacheco3107

    16 mar. 18 en 16:23

Múltiples métodos combinados de pdf usando org.apache.pdfbox:

public void mergePDFFiles(List<File> files,
                          String mergedFileName) {
    try {
        PDFMergerUtility pdfmerger = new PDFMergerUtility();
        for (File file : files) {
            PDDocument document = PDDocument.load(file);
            pdfmerger.setDestinationFileName(mergedFileName);
            pdfmerger.addSource(file);
            pdfmerger.mergeDocuments(MemoryUsageSetting.setupTempFileOnly());
            document.close();
        }
    } catch (IOException e) {
        logger.error("Error to merge files. Error: " + e.getMessage());
    }
}

Desde el programa principal, llame fusionar archivos PDF método utilizando la lista de archivos y el nombre del archivo de destino.

        String mergedFileName = "Merged.pdf";
        mergePDFFiles(files, mergedFileName);

Después de llamar fusionar archivos PDF, cargar archivo fusionado

        File mergedFile = new File(mergedFileName);

package article14;

import java.io.File;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.util.PDFMergerUtility;

public class Pdf
{
    public static void main(String args[])
    {
        new Pdf().createNew();
        new Pdf().combine();
        }

    public void combine()
    {
        try
        {
        PDFMergerUtility mergePdf = new PDFMergerUtility();
        String folder ="pdf";
        File _folder = new File(folder);
        File[] filesInFolder;
        filesInFolder = _folder.listFiles();
        for (File string : filesInFolder)
        {
            mergePdf.addSource(string);    
        }
    mergePdf.setDestinationFileName("Combined.pdf");
    mergePdf.mergeDocuments();
        }
        catch(Exception e)
        {

        }  
    }

public void createNew()
{
    PDDocument document = null;
    try
    {
        String filename="test.pdf";
        document=new PDDocument();
        PDPage blankPage = new PDPage();
        document.addPage( blankPage );
        document.save( filename );
    }
    catch(Exception e)
    {

    }
}

}

  • Tragar excepciones es un mal patrón. catch(Excepción e){ }

    – Lluís Martínez

    11 dic. 17 a las 11:40


¿Cómo fusionar dos archivos PDF en uno en Java?
david w

Si desea combinar dos archivos donde uno se superpone al otro (ejemplo: el documento A es una plantilla y el documento B tiene el texto que desea colocar en la plantilla), esto funciona:

después de crear “doc”, desea escribir su plantilla (templateFile) encima de eso:

   PDDocument watermarkDoc = PDDocument.load(getServletContext()
                .getRealPath(templateFile));
   Overlay overlay = new Overlay();

   overlay.overlay(watermarkDoc, doc);

  • Tragar excepciones es un mal patrón. catch(Excepción e){ }

    – Lluís Martínez

    11 dic. 17 a las 11:40


¿Cómo fusionar dos archivos PDF en uno en Java?
Ricardo Jl Rufino

Uso de iText (PDF existente en bytes)

    public static byte[] mergePDF(List<byte[]> pdfFilesAsByteArray) throws DocumentException, IOException {

    ByteArrayOutputStream outStream = new ByteArrayOutputStream();
    Document document = null;
    PdfCopy writer = null;

    for (byte[] pdfByteArray : pdfFilesAsByteArray) {

        try {
            PdfReader reader = new PdfReader(pdfByteArray);
            int numberOfPages = reader.getNumberOfPages();

            if (document == null) {
                document = new Document(reader.getPageSizeWithRotation(1));
                writer = new PdfCopy(document, outStream); // new
                document.open();
            }
            PdfImportedPage page;
            for (int i = 0; i < numberOfPages;) {
                ++i;
                page = writer.getImportedPage(reader, i);
                writer.addPage(page);
            }
        }

        catch (Exception e) {
            e.printStackTrace();
        }

    }

    document.close();
    outStream.close();
    return outStream.toByteArray();

}

  • El OP dijo claramente “Quiero fusionar muchos archivos PDF en uno usando PDFBox”. iText no es PDFBox.

    – mkl

    18 mayo, 2018 en 21:13

.

¿Ha sido útil esta solución?