Hi all,
I'm just wondering if it's possible to remove the interactible fields (acro fields?) upon saving out a PDF. At present when the PDF goes to preview it's letting you edit the fields that have already been filled in programmatically, but if possible I'd like to lock them down so it's all just a flat, read-only PDF right at the end of the pipeline.
Does that make sense? It might not. It's been a long night.
Cheers!
Hi @sdfereday,
AcroField has read only flag. Is this useful for you instead of removing fields?
acroField.set(PDFName.of('Ff'), PDFNumber.of(
1 << 0 // Read Only
|
1 << 12 // Multiline
));
I uploaded a example below.
https://github.com/Hopding/pdf-lib/issues/205#issuecomment-538655660
Hope this helps.
Thanks @astanet, that does work a treat but it seems to not work on any fields that haven't been interacted with yet curiously. So any that have a value set are fine (I set the values programtically). I'll keep digging anyway, perhaps I'm not getting all of the fields correctly.
Thanks @astanet, that does work a treat but it seems to not work on any fields that haven't been interacted with yet curiously. So any that have a value set are fine (I set the values programtically). I'll keep digging anyway, perhaps I'm not getting all of the fields correctly.
Enable NeedAppearances
acroForm.set(PDFName.of("NeedAppearances"), PDFBool.True);
@sdfereday the approach described by @astanet and @punisher97 is the simplest way to handle this right now in pdf-lib. Some PDF libraries (such as PDFBox) do provide a way to strip out the actual AcroFields themselves and replace them with raw text. However, pdf-lib has no APIs for this, and doing so yourself would require a lot of custom code.
Here's a complete working example for version 1.3.0. It finds all the AcroFields in the document and marks them as read-only, whether or not a value was filled in for them: pdf-lib_read_only_form_fill_example.zip
And here's the gist of the script:
const getAcroForm = pdfDoc => {
return pdfDoc.catalog.lookup(PDFName.of('AcroForm'));
};
const getAcroFields = pdfDoc => {
const acroForm = getAcroForm(pdfDoc);
if (!acroForm) return [];
const fieldRefs = acroForm.lookupMaybe(PDFName.of('Fields'), PDFArray);
if (!fieldRefs) return [];
const fields = new Array(fieldRefs.size());
for (let idx = 0, len = fieldRefs.size(); idx < len; idx++) {
fields[idx] = fieldRefs.lookup(idx);
}
return fields;
};
const lockField = acroField => {
acroField.set(PDFName.of('Ff'), PDFNumber.of(1 << 0 /* Read Only */));
};
(async () => {
const pdfDoc = await PDFDocument.load(fs.readFileSync('./template.pdf'));
const acroForm = getAcroForm(pdfDoc);
acroForm.set(PDFName.of('NeedAppearances'), PDFBool.True);
// Now make all the fields read-only
const acroFields = getAcroFields(pdfDoc);
acroFields.forEach(field => lockField(field));
const pdfBytes = await pdfDoc.save();
})();
I hope this helps. Please let me know if you have any additional questions!
Most helpful comment
@sdfereday the approach described by @astanet and @punisher97 is the simplest way to handle this right now in pdf-lib. Some PDF libraries (such as PDFBox) do provide a way to strip out the actual AcroFields themselves and replace them with raw text. However, pdf-lib has no APIs for this, and doing so yourself would require a lot of custom code.
Here's a complete working example for version
1.3.0. It finds all the AcroFields in the document and marks them as read-only, whether or not a value was filled in for them: pdf-lib_read_only_form_fill_example.zipAnd here's the gist of the script:
I hope this helps. Please let me know if you have any additional questions!