我正在使用 PDFBox 3.0.0 和 java 17 来合并许多 PDF 文档。
要合并的文件源预先使用 GhostScript 从一些普通 PDF 转换为每页都有图像的 PDF。每个 PDF 的每一页都是使用 Ghostscript 转换 PDF 后的图像。
有时我会合并相同的文件。 例如,我想再次合并 input-gs.pdf、input2-gs.pdf 和第一个文件 input-gs.pdf。
当我合并这些文件时,输出的大小很大并且没有优化。
我想减小合并后的PDF文件的大小,我正在寻找是否可以在字典中的所有PDF中使用一次相同的图像,并使用其参考而不需要对内存中的所有图像进行充电。
我搜索是否有解决方案为最终合并的 PDF 中的每个图像设置键或唯一名称,并在稍后使用这些图像的名称或引用来再次合并同一文件。
private static void mergeFiles() throws IOException {
RandomAccessStreamCache.StreamCacheCreateFunction streamCache =
IOUtils.createMemoryOnlyStreamCache();
PDDocument emptyDocument = createBlankValidDocument();
PDFMergerUtility pdfMergerUtility = new PDFMergerUtility();
pdfMergerUtility.setDocumentMergeMode(
PDFMergerUtility.DocumentMergeMode.OPTIMIZE_RESOURCES_MODE);
pdfMergerUtility.setAcroFormMergeMode(PDFMergerUtility.AcroFormMergeMode.JOIN_FORM_FIELDS_MODE);
appendFile("input-gs.pdf", streamCache, emptyDocument, pdfMergerUtility);
appendFile("input2-gs.pdf", streamCache, emptyDocument, pdfMergerUtility);
appendFile("input-gs.pdf", streamCache, emptyDocument, pdfMergerUtility);
emptyDocument.save("output-merged.pdf");
}
private static void appendFile(String filename,
RandomAccessStreamCache.StreamCacheCreateFunction streamCache,
PDDocument emptyDocument,
PDFMergerUtility pdfMergerUtility) throws IOException {
File file = new File(filename);
PDDocument document = Loader.loadPDF(new RandomAccessReadBuffer(new FileInputStream(file)),
streamCache);
pdfMergerUtility.appendDocument(emptyDocument, document);
}
public static PDDocument createBlankValidDocument() {
try {
RandomAccessStreamCache.StreamCacheCreateFunction streamCache =
IOUtils.createMemoryOnlyStreamCache();
PDDocument document = new PDDocument(streamCache);
// Conformance level + Part
XMPMetadata xmp = XMPMetadata.createXMPMetadata();
PDFAIdentificationSchema id = xmp.createAndAddPDFAIdentificationSchema();
id.setConformance("A");
id.setPart(1);
// Metadata
setMetadata(document, xmp);
return document;
} catch (Exception e) {
}
return null;
}
private static void setMetadata(PDDocument document, XMPMetadata xmp)
throws TransformerException, IOException {
PDDocumentCatalog catalogue = document.getDocumentCatalog();
XmpSerializer serializer = new XmpSerializer();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
serializer.serialize(xmp, outputStream, true);
PDMetadata metadata = new PDMetadata(document);
metadata.importXMPMetadata(outputStream.toByteArray());
catalogue.setMetadata(metadata);
}
我在这篇文章中找到了一个代码如何使用pdfbox或其他java库减少合并的PDF/A-1b文件的大小搜索文件中的复杂对象并合并它,我希望如果可能的话找到一个解决方案不要使用大量内存,因为有时我会有 100 个包含很多页面的文件。
提前谢谢您。
如果,正如您所说,您正在重复使用相同的文件(或同一文件中的页面),那么生成的图像对象应该是相同的。
在你的输出上尝试
cpdf -squeeze out.pdf -o out2.pdf
,以检验这个假设。如果确实发生了这种情况,相同的对象将被合并,并且大小将减小到您期望的大小。
(顺便说一句,如果您多次使用文件中的范围,Cpdf 的合并应该正确共享数据。例如,
cpdf a.pdf 1-3 b.pdf a.pdf 1-10 c.pdf
应该仅包含 a.pdf 第 1-3 页的内容一次,即使这些页面出现输出中的两次)。