如何在Java中将两个PDF文件合并为一个?


74

我想使用PDFBox将许多PDF文件合并为一个,这就是我所做的:

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

哪里pdfFiles是一个ArrayList<String>包含了所有的PDF文件。

当我运行上面的代码时,我总是得到:

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

难道我做错了什么?还有其他方法吗?


1
有人指出了iText [ java-x.blogspot.com/2006/11/merge-pdf-files-with-itext.html],然后删除了答案。它的工作,并为此感谢。
Lipis

链接可能有助于寻找答案的人。
java_learner 2013年

Answers:


134

为什么不使用pdfbox的PDFMergerUtility

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

1
也可以,但是我也使用PDFBox来创建PDF。
Lipis

是否可以合并已扫描图像的PDF和以前为PDF的PDF?
Ragesh Kr 2015年

3
@RageshKr:据我了解,它将合并任何PDF,无论其内容如何。
cherouvim 2015年

1
有什么办法可以在每页中为生成的pdf提及页面编号吗?
Prateek Singh

如果pdf文件具有密码,可以使用它吗?
编码器


11

这是一个随时可用的代码,将四个pdf文件与来自http://central.maven.org/maven2/com/itextpdf/itextpdf/5.5.0/itextpdf-5.5.0.jar的itext.jar合并,更多有关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();
    }
    }
}

3
这个问题显然被标记为pdfbox。您提出了itext的解决方案。因此,您的答案是题外话。(话虽如此,您的iText解决方案也是一个不好的解决方案,iText开发人员通常会建议这样做,因为它放弃了交互式功能并且忽略了旋转和页面大小。)
mkl

然后标题应该是“如何使用PdfBox在Java中将两个PDF文件合并为一个文件”
Lluis Martinez

3
另外,iText带有讨厌的许可证。
Daniel Bo

此示例被命名为IncorrectExample,因为这通常不能解决旋转页面或合并文档的问题。正确的方法不是使用Document / PdfWriter,而是使用PdfStamper,PdfCopy或PdfSmartCopy。但是:在上述问题中,情况非常特殊,在这种情况下使用此示例是合理的:developers.itextpdf.com/examples/merging-pdf-documents-itext5/…–
victorpacheco3107

6

使用org.apache.pdfbox的多种pdf合并方法:

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

在主程序中,使用文件列表和目标文件名调用mergePDFFiles方法。

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

调用mergePDFFiles之后,加载合并的文件

        File mergedFile = new File(mergedFileName);

4
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)
    {

    }
}

}

吞咽异常是一种不良模式。catch(Exception e){}
Lluis Martinez

1

如果要合并两个文件,其中一个文件重叠另一个文件(例如:文档A是模板,而文档B具有要放在模板上的文本),则可以这样做:

创建“ doc”后,您想在其上编写模板(templateFile)-

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

   overlay.overlay(watermarkDoc, doc);

0

使用iText(以字节为单位的现有PDF)

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

}

OP明确表示“我想使用PDFBox将许多PDF文件合并为一个文件”。iText不是PDFBox。
mkl
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.