-
-
Notifications
You must be signed in to change notification settings - Fork 706
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
[Feature Request]: Embed files #229
Comments
Hello @zimt28! This certainly seems like an interesting and useful feature. It shouldn't be terribly difficult to implement either. The PDF specification documents file attachments in section 7.11.4 Embedded File Streams and 12.5.6.15 File Attachment Annotations. |
To be clear, creating a file attachment is already possible to do with pdf-lib. It just entails creating particular dictionaries and streams, and wiring them up in the right way. pdf-lib already provides access to the low-level primitives necessary to do this. So this feature would just involve creating a nice API to abstract away the nitty gritty of what's involved here. |
Hello @Hopding, I would like to contribute to this library with this feature. I've read the sections you mentioned in the PDF specification, and tried some different things, but I'm kind of lost with all the dictionaries and streams of the library. It seems that the embedded file streams consist of 2 objects: A descriptor, which defines de And a FlatDecode Stream, which has the file contents it seems. Could you help me a bit out? A hint which low-level primitives I should take a look at? And eventually how to wire them up? Thank you very much! |
Hello @sebastinez! Adding file embedding functionality to Here's a basic working example that creates a new document and attaches an image file to it. Let me know if you have any questions. import {
PDFDocument,
PDFName,
PDFDict,
PDFArray,
PDFString,
PDFHexString,
PDFRef,
} from 'pdf-lib';
const createEmbeddedFile = (
pdfDoc: PDFDocument,
file: Uint8Array,
fileName: string,
mimeType: string,
) => {
const embeddedFileStream = pdfDoc.context.flateStream(file, {
Type: 'EmbeddedFile',
Subtype: PDFName.of(mimeType),
});
const embeddedFileStreamRef = pdfDoc.context.register(embeddedFileStream);
const fileSpecDict = pdfDoc.context.obj({
Type: 'Filespec',
F: PDFString.of(fileName),
UF: PDFHexString.fromText(fileName),
EF: { F: embeddedFileStreamRef },
});
const fileSpecDictRef = pdfDoc.context.register(fileSpecDict);
return fileSpecDictRef;
};
const insertEmbeddedFile = (
pdfDoc: PDFDocument,
fileName: string,
fileSpecRef: PDFRef,
) => {
if (!pdfDoc.catalog.has(PDFName.of('Names'))) {
pdfDoc.catalog.set(PDFName.of('Names'), pdfDoc.context.obj({}));
}
const Names = pdfDoc.catalog.lookup(PDFName.of('Names'), PDFDict);
if (!Names.has(PDFName.of('EmbeddedFiles'))) {
Names.set(PDFName.of('EmbeddedFiles'), pdfDoc.context.obj({}));
}
const EmbeddedFiles = Names.lookup(PDFName.of('EmbeddedFiles'), PDFDict);
if (!EmbeddedFiles.has(PDFName.of('Names'))) {
EmbeddedFiles.set(PDFName.of('Names'), pdfDoc.context.obj([]));
}
const EFNames = EmbeddedFiles.lookup(PDFName.of('Names'), PDFArray);
EFNames.push(PDFHexString.fromText(fileName));
EFNames.push(fileSpecRef);
};
(async () => {
const pdfDoc = await PDFDocument.create();
const page = pdfDoc.addPage();
page.drawText('This is a document with an attachment', { x: 100, y: 700 });
const jpgUrl = 'https://pdf-lib.js.org/assets/cat_riding_unicorn.jpg';
const jpgBuffer = await fetch(jpgUrl).then((res) => res.arrayBuffer());
const file = new Uint8Array(jpgBuffer);
const fileName = 'cat_riding_unicorn.jpg';
const mimeType = 'image/jpeg';
const fileSpecRef = createEmbeddedFile(pdfDoc, file, fileName, mimeType);
insertEmbeddedFile(pdfDoc, fileName, fileSpecRef);
const pdfBytes = await pdfDoc.save();
})(); |
Version You can install this new version with npm:
It's also available on unpkg: As well as jsDelivr: |
I want to generate
ZUGFeRD
invoices, which is a German standard for XML files with a certain structure embedded in a PDF/A-3 file.I'll create feature requests for both requirements but here I'm asking for attachment embedding support. I couldn't find this in any other JS pdf library and think it's something quite some people might want.
The text was updated successfully, but these errors were encountered: