Hopding / pdf-lib

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

Fill Form - Either missing template or form fields undefined #1076

Closed jbw09 closed 2 years ago

jbw09 commented 3 years ago

What were you trying to do?

Fill my template form

Why were you trying to do this?

So I can collect my salary twice a month :)

How did you attempt to do it?

I saw PDFescape in a post and gave that a shot to be able to edit PDF form field names. Ran my prog and indeed form fields filled but the rest of the contents from my template file were missing.

I tried the Fill Form example file (dod_character.pdf) and it couldn't find the form field names, so I also loaded that in PDFescape and saved from there, and then the same result of the rest of the template missing but form fields filled.

I thought maybe PDFescape could be the issue so I purchased the Adobe trial to be able to edit the form field names but there again, pdf-lib doesn't find them (Error: PDFDocument has no form field with the name "prodCode") even though definitely saved as such -

image

What actually happened?

Details 1 section up

What did you expect to happen?

For my template file to come through with fields filled

How can we reproduce the issue?

My code (nearly copied from yours) -

const { PDFDocument } = require('pdf-lib');
const fs = require('fs');

(async () => {

    const pdfUTF8 = fs.readFileSync('./test.pdf','utf8')
    var formPdfBytes = new TextEncoder("utf-8").encode(pdfUTF8);

    // Load a PDF with form fields
    const pdfDoc = await PDFDocument.load(formPdfBytes)

    // Get the form containing all the fields
    const form = pdfDoc.getForm()

    // Get all fields in the PDF by their names
    const productCodeField = form.getTextField('prodCode')
    const certNumberField = form.getTextField('certNumber')

    productCodeField.setText('Product code here')
    certNumberField.setText('Cert number here')

    // Serialize the PDFDocument to bytes (a Uint8Array)
    const pdfBytes = await pdfDoc.save()

    const data = fs.writeFileSync('./done.pdf', new Buffer.from(pdfBytes))

})().catch(e => {
  console.log(e)
});

Version

1.17.0

What environment are you running pdf-lib in?

Node

Required Reading

Additional Notes

No response

Hopding commented 3 years ago

Hello @jbw09! The code snippet you shared references ./test.pdf. Would you please attach that file (or a functionally equivalent file) to the report so I can try to reproduce the issue?

jbw09 commented 3 years ago

I really appreciate you looking into it, @Hopding! OK to call you Andrew? Jay here :)

I tested with a bunch of different files so just had test.pdf as a placeholder.

Solis5YrTest.pdf - this is the one saved from PDFescape where the rest of the template disappears but the fields are filled correctly (attachment removed)

Solis5YrTest-2.pdf - this one saved with my trial of Adobe and it doesn't find the field names, ie 'Error: PDFDocument has no form field with the name "prodCode"' (attachment removed)

I also tried these same actions (PDFescape and editing&saving with Adobe) with your example Fill Form pdf (dod_character.pdf) with the same results.

dcsline commented 3 years ago

@jbw09: I have checked your test code - without problems! A Question, why do you not using Hopdings program posibility to read the field names. I had built-in this code

const fields = pdfDoc.getForm().getFields() const fieldNames = fields.map((f) => f.getName()); fields.forEach(field => { const name = field.getName() console.log('Field name:', name); const widgets = field.acroField.getWidgets(); })

in the sample and could see the following field names: Field name: prodCode Field name: certNumber Field name: model Field name: serial Field name: date

jbw09 commented 3 years ago

@dcsline thank you for taking a look!

With Solis5YrTest.pdf, yes I can read the field names. The problem with that one is the rest of the template disappears, only the field names get updated/come through.

With Solis5YrTest-2.pdf, the field names are not found.

jbw09 commented 2 years ago

@Hopding could you please have a look?

dcsline commented 2 years ago

@jbw09: I cannot agree with you. In both cases the field names were shown to me (see Attachment Test_Solis5YrTest pdf Test_Solis5YrTest-2 pdf )

jbw09 commented 2 years ago

@Hopding @dcsline I don't know what to say other than I am not the guy who goes around on the internet wasting my time and others so please don't take your trust issues out on me! :)

Solis5YrTest (template missing) - image

Solis5YrTest-2 (error) - image

Wondering if it could be something in my environment then? I'm on Node 14.17.6 and I rolled back to try with 12.22.7 too, same results.

Also note the 'invalid object' logging in both of mine (not seen in yours).

dcsline commented 2 years ago

@jbw09 There isn't a trust issues. I am only a pdf-lib user. That's why I'm also following the issues. When it is possible (as with your issue) I test the documents / processes. And in your case I came to a different conclusion. I tested it under Node V16.3.0

jbw09 commented 2 years ago

tested with node v16.13.0, same results

dcsline commented 2 years ago

From the source of another project, I quickly created the test program for your test files. This program uses expressjs and socketjs. The PDF processing and backup is done in JS. The file name is communicated to the HTML page, which is then set as the source for the document to be displayed in the IFrame.

dcsline commented 2 years ago

@jbw09 I have looked into the screenshot and have seen - you are used another pdf loading process. With your three code lines i could reproduce your error 1076_reproduce_error s.

jbw09 commented 2 years ago

@dcsline DUDE! I appreciate you taking another look!!! That did it :)

I can't even remember now where I got the TextEncoder complication from, I'm sure I probably copied it off stackoverflow.

The good thing with getting it to work with pdf-lib too (and on the one saved at pdfescape) is no subscription (like to Adobe for instance) ever needed :)

Thanks again, @dcsline!

dcsline commented 2 years ago

@Hopding: Does this statement make sense new TextEncoder("utf-8").encode(pdfUTF8); ???

Hopding commented 2 years ago

@dcsline thanks for jumping in and helping out with this!

Hopding commented 2 years ago

Closing as the issue is solved.

In case anybody stumbles on this in the future:

❌ Incorrect

const pdfUTF8 = fs.readFileSync('./test.pdf','utf8')
var formPdfBytes = new TextEncoder("utf-8").encode(pdfUTF8);
const pdfDoc = await PDFDocument.load(formPdfBytes)

✅ Correct

const formPdfBytes = fs.readFileSync('./test.pdf')
const pdfDoc = await PDFDocument.load(formPdfBytes)