Hopding / pdf-lib

Create and modify PDF documents in any JavaScript environment
https://pdf-lib.js.org
MIT License
6.6k stars 635 forks source link

copyPages with forms inside of it #1587

Open AlbaneseRemy opened 6 months ago

AlbaneseRemy commented 6 months ago

What were you trying to do?

Basically, I have a project that consists in generating a pdf file from a template with a form inside of it.

My template is a double-sided pdf, the first one being the cover page, and the second one being the content. In the content, I have a form : a text-field, that will contain some text, and a button that will contain an image (I used the example in the fill form page of the PDF-Lib website for the button with image)

The goal is to generate a lot of pdfs at once from a json file that will contain a list of element with the text and the image that will be used.

How did you attempt to do it?

I'm iterating over my json input. For each iteration, I will get my TextField, my Button, and add my text and image into them. Then, I will use the copyPages method into my final pdfFile, and add the page to it. Finally, I'm adding it to my response for my local client.

` const newPdfDoc = await PDFDocument.PDFDocument.create(); const jsonInput = JSON.parse(req.body.json);

for await (const element of jsonInput.keys) { const pdfBuffer = await fs.readFile('./public/uploads/test.pdf'); const pdfDoc = await PDFDocument.PDFDocument.load(pdfBuffer);

        const response = await fetch('http://localhost:8000/generate-qrcode-return-base64', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({ text: element.url, darkColor: '#ffffff', lightColor: '#0000' })
        });
        const qrCodeImageBytes = await response.text();
        const qrCodeImage = await pdfDoc.embedPng(qrCodeImageBytes);

        const form = pdfDoc.getForm();
        const textField = form.getTextField('activation-key');
        textField.setText(element.key);
        textField.setAlignment(PDFDocument.TextAlignment.Center);

        const imageButton = form.getButton('qrcode_af_image');
        imageButton.setImage(qrCodeImage);

        const [firstPage, secondPage] = await newPdfDoc.copyPages(pdfDoc, [0, 1]);
                    newPdfDoc.addPage(firstPage);
                    newPdfDoc.addPage(secondPage);
                }

`

What actually happened?

I get my PDF, I can open it. Each image is different, but the text displayed is the same for every page. Obviously, my json file has different text, and if I console.log(jsonInput.text), it will log the text that is supposed to be shown.

What did you expect to happen?

Each page of the pdf should have a different text and image.

How can we reproduce the issue?

Create a node.js local server, here's the post method code. I replaced the image by the one used in the pdf lib demo.

`

app.post('/return-pdf-with-json', async (req, res) => {
    try {
        console.time();
        const newPdfDoc = await PDFDocument.PDFDocument.create();

        const { json } = req.body;
        const jsonInput = JSON.parse(json);

        for await (const element of jsonInput.keys) {
            const pdfBuffer = await fs.readFile('./public/uploads/test.pdf');
            const pdfDoc = await PDFDocument.PDFDocument.load(pdfBuffer);

            const imageUrl = 'https://pdf-lib.js.org/assets/mario_emblem.png'
            const qrCodeImageBytes = await fetch(imageUrl).then(res => res.arrayBuffer())
            const qrCodeImage = await pdfDoc.embedPng(qrCodeImageBytes);

            const form = pdfDoc.getForm();
            const textField = form.getTextField('activation-key');
            textField.setText(element.key);
            textField.setAlignment(PDFDocument.TextAlignment.Center);
            const imageButton = form.getButton('qrcode_af_image');
            imageButton.setImage(qrCodeImage);

            const [firstPage, secondPage] = await newPdfDoc.copyPages(pdfDoc, [0, 1]);
            newPdfDoc.addPage(firstPage);
            newPdfDoc.addPage(secondPage);
        }

        const finalPdfBytes = await newPdfDoc.save();
        res.setHeader('Content-Disposition', 'attachment; filename=download.pdf');
        res.setHeader('Content-Type', 'application/pdf');
        res.send(Buffer.from(finalPdfBytes));
    } catch (err) {
        console.error('Error generating PDF, ' + err);
        res.status(500).send('Error generating PDF, ' + err);
    }
    console.timeEnd();
});

`

Also, here's the json I'm using: keys.json

Version

1.17.1

What environment are you running pdf-lib in?

Browser, Node

Checklist

Additional Notes

No response