Class PdfMerger
- java.lang.Object
-
- com.pd4ml.pdf.merge.PdfMerger
-
public final class PdfMerger extends java.lang.ObjectPublic entry point of the PD4ML PDF merge API. Combines page ranges selected independently from two (or more) existing PDF files into one output document, built entirely on the pd4mlcom.pd4ml.pdf.cosobject model/parser (no PDFBox, no other PDF library) -- the same foundationcom.pd4ml.pdf.signis built on.Every selected page is deep-cloned into a fresh object-numbering space (see
COSObjectImporter), so the two sources' indirect object numbers never collide, regardless of how much they overlap in the originals. Each selected page's accessibility structure (tagging) is reconciled into a single merged/StructTreeRooton a best-effort basis (seeStructureTreeMerger): pages from a tagged source keep their structure, pages from an untagged source are simply included without any, and the merged document is tagged overall only if at least one selected page contributed structure.Encrypted source PDFs are supported: pass the source's user or owner password to the password-taking
addSourceoverload (an empty or omitted password is tried too, covering the common case of a document that only restricts permissions with an owner password). The pd4ml COS reader decrypts transparently while parsing, so every page cloned from an encrypted source is handled exactly like one from a plain PDF; a source is only rejected if the given password fails to open it.The merged output itself can also be encrypted -- see
encryptOutput(String, String)/encryptOutput(PdfEncryptor.Options).With exactly one source added, calling
selectPages(...)is optional: with no selection, the result is that source's own pages, in their original order (decrypted, if the source was encrypted, unlessencryptOutput(java.lang.String, java.lang.String)was also called) -- i.e. a filter/decrypt/re-encrypt pass rather than a true merge. With two or more sources, every source still requires an explicitselectPages(...)call.Not supported (v1): merging
/AcroFormfield hierarchies, named destinations, or outlines (their absence doesn't corrupt the output -- widget annotations still come along fine as ordinary page/Annots-- only the document-level field tree/outline tree is not reconciled).Thread-safety: a single
PdfMergerinstance may safely be shared across threads --addSource(...)/encryptOutput(...)may be called concurrently (e.g. to add several sources in parallel), andmergeToBytes()/merge(...)always reads a consistent snapshot of whatever sources had been fully added by the time it runs. A source is only guaranteed to be included in a merge call that starts after itsaddSource(...)call has returned; racingaddSource(...)against an in-flightmergeToBytes()call on the same instance may or may not pick it up, but never corrupts either call's result. EachPdfMergeSourcereturned byaddSource(...)is likewise safe to hand off to another thread before that thread callsselectPages(...)on it.Example
PdfMerger merger = new PdfMerger(); merger.addSource(pdfABytes).selectPages("2-5,odd"); merger.addSource(pdfBBytes, "sourceBPassword").selectPages("1,3,6+"); merger.encryptOutput("openPassword", "ownerPassword"); byte[] merged = merger.mergeToBytes();
-
-
Constructor Summary
Constructors Constructor Description PdfMerger()
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description PdfMergeSourceaddSource(byte[] pdfBytes)PdfMergeSourceaddSource(byte[] pdfBytes, java.lang.String password)PdfMergeSourceaddSource(java.io.File pdfFile)PdfMergeSourceaddSource(java.io.File pdfFile, java.lang.String password)PdfMergeSourceaddSource(java.io.InputStream pdfStream)PdfMergeSourceaddSource(java.io.InputStream pdfStream, java.lang.String password)PdfMergerencryptOutput(PdfEncryptor.Options options)PdfMergerencryptOutput(java.lang.String userPassword, java.lang.String ownerPassword)Configures the merged output to be encrypted with AES-256, the modern default.PdfMergerinfo(java.lang.String key, java.lang.String value)Sets (or, ifvalueisnull, leaves unset) one/Infodictionary entry (e.g.voidmerge(java.io.File outputFile)voidmerge(java.io.OutputStream out)PdfMergermergeOutlines(boolean enabled)Opt-in (defaultfalse, so no existing caller's output changes): splice each source's own outline (bookmark) tree onto the merged output's, in source-processing order -- seeOutlineMerger's own javadoc for the exact splice semantics and its one documented scope limitation (a source outline node pointing at a page that wasn't itself selected for the merge is not pruned -- only safe to enable when every page of every outline-contributing source is included in the merge).byte[]mergeToBytes()
-
-
-
Method Detail
-
addSource
public PdfMergeSource addSource(byte[] pdfBytes) throws PdfMergeException
- Throws:
PdfMergeException
-
addSource
public PdfMergeSource addSource(byte[] pdfBytes, java.lang.String password) throws PdfMergeException
- Throws:
PdfMergeException
-
addSource
public PdfMergeSource addSource(java.io.File pdfFile) throws PdfMergeException
- Throws:
PdfMergeException
-
addSource
public PdfMergeSource addSource(java.io.File pdfFile, java.lang.String password) throws PdfMergeException
- Throws:
PdfMergeException
-
addSource
public PdfMergeSource addSource(java.io.InputStream pdfStream) throws PdfMergeException
- Throws:
PdfMergeException
-
addSource
public PdfMergeSource addSource(java.io.InputStream pdfStream, java.lang.String password) throws PdfMergeException
- Throws:
PdfMergeException
-
encryptOutput
public PdfMerger encryptOutput(java.lang.String userPassword, java.lang.String ownerPassword)
Configures the merged output to be encrypted with AES-256, the modern default. For finer control (algorithm choice, permission bits) useencryptOutput(PdfEncryptor.Options)instead.
-
encryptOutput
public PdfMerger encryptOutput(PdfEncryptor.Options options)
-
mergeOutlines
public PdfMerger mergeOutlines(boolean enabled)
Opt-in (defaultfalse, so no existing caller's output changes): splice each source's own outline (bookmark) tree onto the merged output's, in source-processing order -- seeOutlineMerger's own javadoc for the exact splice semantics and its one documented scope limitation (a source outline node pointing at a page that wasn't itself selected for the merge is not pruned -- only safe to enable when every page of every outline-contributing source is included in the merge).
-
info
public PdfMerger info(java.lang.String key, java.lang.String value)
Sets (or, ifvalueisnull, leaves unset) one/Infodictionary entry (e.g."Title","Author") on the merged output. A merge builds a brand-new document from scratch and, unlike a single source's own trailer, has no/Infoof its own to start from -- callers that want the merged file to carry over a document's existing metadata (e.g.PdfDocumentBase#append, which treats the documentappend(...)was called on as the one that "continues") must copy the values across explicitly via this method before callingmergeToBytes().
-
merge
public void merge(java.io.OutputStream out) throws PdfMergeException- Throws:
PdfMergeException
-
merge
public void merge(java.io.File outputFile) throws PdfMergeException- Throws:
PdfMergeException
-
mergeToBytes
public byte[] mergeToBytes() throws PdfMergeException- Throws:
PdfMergeException
-
-