如何在Java中将两个PDF文件合并为一个?
Posted
技术标签:
【中文标题】如何在Java中将两个PDF文件合并为一个?【英文标题】:How to merge two PDF files into one in Java? 【发布时间】:2011-04-04 20:39:46 【问题描述】:我想使用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
是一个包含所有PDF 文件的ArrayList<String>
。
当我运行上述内容时,我总是得到:
org.apache.pdfbox.exceptions.COSVisitorException: Bad file descriptor
我做错了吗?还有其他方法吗?
【问题讨论】:
有人指出 iText [java-x.blogspot.com/2006/11/merge-pdf-files-with-itext.html] 然后删除了答案。它奏效了,谢谢。 link 可能会帮助寻找答案的人。 【参考方案1】:快速的 Google 搜索返回了这个错误:"Bad file descriptor while saving a document w. imported PDFs"。
您似乎需要将要合并的 PDF 保持打开状态,直到您保存并关闭合并的 PDF。
【讨论】:
虽然这个帖子已经有两年了,但这解决了问题。你必须让它们保持开放!【参考方案2】:为什么不用pdfbox的PDFMergerUtility呢?
PDFMergerUtility ut = new PDFMergerUtility();
ut.addSource(...);
ut.addSource(...);
ut.addSource(...);
ut.setDestinationFileName(...);
ut.mergeDocuments();
【讨论】:
也可以,但我也使用 PDFBox 创建 PDF。 它是否允许合并包含扫描图像的 PDF 和编写的 PDF? @RageshKr:据我了解,无论其内容如何,它都会合并任何 PDF。 有没有办法在每个页面中提到结果 pdf 的 page-no ?? pdf文件有密码可以用吗?【参考方案3】: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)
【讨论】:
吞下异常是一种不好的模式。捕获(异常 e) 【参考方案4】:如果您想合并两个文件,其中一个文件覆盖另一个文件(例如:文档 A 是一个模板,而文档 B 有您要放置在模板上的文本),这可行:
创建“doc”后,您想在其上编写模板(templateFile)-
PDDocument watermarkDoc = PDDocument.load(getServletContext()
.getRealPath(templateFile));
Overlay overlay = new Overlay();
overlay.overlay(watermarkDoc, doc);
【讨论】:
【参考方案5】:这是一个即用型代码,将四个 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();
【讨论】:
这个问题显然被标记为pdfbox。您提出了itext 的解决方案。因此,您的答案是题外话。 (话虽如此,您的 iText 解决方案也是一个糟糕的解决方案,iText 开发人员通常会建议反对,因为它会放弃交互功能并忽略旋转和页面大小。) 那么标题应该是“Java中如何用PdfBox将两个PDF文件合并为一个” 此外,iText 带有一个令人讨厌的许可证。 这个例子被命名为 IncorrectExample 因为这不是你通常用来解决旋转页面问题的方法,也不是合并文档的方法。正确的方法不是使用 Document / PdfWriter,而是使用 PdfStamper、PdfCopy 或 PdfSmartCopy。但是:在上述问题中,情况非常特殊,在这种情况下使用此示例是合理的:developers.itextpdf.com/examples/merging-pdf-documents-itext5/…【参考方案6】:使用 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。【参考方案7】:使用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);
【讨论】:
为什么要循环设置目标文件名? 为什么要创建“文档”而不是循环使用它?以上是关于如何在Java中将两个PDF文件合并为一个?的主要内容,如果未能解决你的问题,请参考以下文章