pdf-lib icon indicating copy to clipboard operation
pdf-lib copied to clipboard

Splitting a PDF into many new PDFs - (foreign) PDF document error

Open grimeytron opened this issue 3 years ago • 2 comments

What were you trying to do?

Hello,

I have been trying to rework how I was using copyPages. Previously I had it in a loop (which is stated as being an anti-pattern), and it was working but it was eating up too much memory on the server and crashing the process. So I looked through the issues and saw alot of comments about how to do this correctly. After trying I get a ""A page passed to PDFDocument.addPage or PDFDocument.insertPage was from a different (foreign) PDF document. If you want to copy pages from one PDFDocument to another, you must use PDFDocument.copyPages(...) to copy the pages before adding or inserting them."," exception so I was wondering if anyone could guide me the correct way.

I think my issue is that I cant recreate 1 initial PDF to use for copy pages, I have to dynamically create one for each page, but who knows. Anywho thanks for your time!

How did you attempt to do it?

Before (incorrect but working) :

for(let i: number = 0; i < pageCount; i++) {
                            upsertPromises.push(
                                pdfLib.PDFDocument.create()
                                    .then((newDocument) => {
                                        return newDocument.copyPages(multiPDFDoc, [i])
                                            .then((copiedPage) => {
                                                newDocument.addPage(copiedPage[0]);
        
                                                return newDocument.saveAsBase64()
                                                    .then((fileBase64) => {
        
                                                        return fileBase64;
                                                    });
                                            });
                                    })    
                            );
                        }

New attempt after referencing https://github.com/Hopding/pdf-lib/issues/47#issuecomment-569315318 :

function copyPage(originalPage): PDFPage {
        const cloneNode = originalPage.node.clone();
    
        const { Contents } = originalPage.node.normalizedEntries();
        if (Contents) cloneNode.set(PDFName.of('Contents'), Contents.clone());
    
        const cloneRef = originalPage.doc.context.register(cloneNode);
        const clonePage = PDFPage.of(cloneNode, cloneRef, originalPage.doc);
        return clonePage;
    }
......
                return pdfLib.PDFDocument.load(fileBase64)
                    .then((multiPDFDoc) => { 
                        return multiPDFDoc.copyPages(multiPDFDoc, multiPDFDoc.getPageIndices())
                            .then((copiedPages) => {
                                copiedPages.forEach((copiedPage) =>{ 
                                    upsertPromises.push(
                                        pdfLib.PDFDocument.create()
                                            .then((newPDF) => {
                                                newPDF.addPage(copyPage(copiedPage));
            
                                                return newPDF.saveAsBase64()
                                                    .then((fileBase64) => {
        
                                                        return fileBase64;
                                                    });                                                                                                                                                                                    
                                            })   
                                    );
                                }); 
........

What actually happened?

{
    "message": "A `page` passed to `PDFDocument.addPage` or `PDFDocument.insertPage` was from a different (foreign) PDF document. If you want to copy pages from one PDFDocument to another, you must use `PDFDocument.copyPages(...)` to copy the pages before adding or inserting them.",
    "success": false
}

What did you expect to happen?

PDFs to split accordingly into 1 file per each page from the initial PDF

How can we reproduce the issue?

in your copyPages example try a loop like I have, should reproduce.

Version

1.17.1

What environment are you running pdf-lib in?

Node

Checklist

  • [X] My report includes a Short, Self Contained, Correct (Compilable) Example.
  • [ ] I have attached all PDFs, images, and other files needed to run my SSCCE.

Additional Notes

No response

grimeytron avatar Mar 15 '22 20:03 grimeytron

Hello,

Here is code that accomplishes the task you're aiming for. Note, you have to copy a single page at a time because you intend to put each page on it's own document.

    Promise.all(multiPDFDoc.getPages().map(function(_, index) {
        return PDFDocument.create().then(function(newDocument) {
            return newDocument.copyPages(multiPDFDoc, [index]).then(function(copiedPages) {
                newDocument.addPage(copiedPages[0]);
                return newDocument;
            });
        }).then(function(newDocument) {
            return newDocument.saveAsBase64()
        });
    }));

this will make a single promise that resolves with an array of all the individual page pdfs as their base64 equivalent

Trapfether avatar Apr 16 '22 04:04 Trapfether

Facing the same error as well. Are there any updates on this?

Fraktbestilling avatar Mar 06 '24 14:03 Fraktbestilling