Reputation: 117
I'm trying to merge two pdf files on frontend using javascript and pdf-lib library. I found this snippet pdf-lib in github repository:
async function mergePdfs(pdfsToMerge: string[]) {
const mergedPdf = await PDFDocument.create();
for (const pdfCopyDoc of pdfsToMerge) {
const pdfBytes = fs.readFileSync(pdfCopyDoc);
const pdf = await PDFDocument.load(pdfBytes);
const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
copiedPages.forEach((page) => {
mergedPdf.addPage(page);
});
}
const mergedPdfFile = await mergedPdf.save();
return mergedPdfFile;
}
But as I see this snipped is for nodejs (there's no fs.readfilesync
in browser javascript). So I have 2 questions:
pdfsToMerge(string: [])
? I have variables containing urls to pdf1 and pdfbase64
code of these pdfs. How can I use this snippet not using fs.readfilesync
like in nodejs but on frontend?Many thanks in advance!
Upvotes: 1
Views: 9009
Reputation: 19
Your version number should be newest pdf-lib
THen sequence of events matters. Here is function i use must be in order of event I use is with data or emtpy to get filled or non filled pdf files
async copyPages(sale: Sale, url1, urlArray, isWithData, isEmptyForm) {
this.pdfService.getIsEmpty().subscribe(data => { isEmptyForm = data; });
this.pdfService.getIsWithData().subscribe(data => { isWithData = data; });
console.log(urlArray);
let donorBytes = [];
let donorBytesFInal = [];
let donorPage = [];
let donorDoc = [];
/**
* first page get bytes from url
* then load data
* then convert the data bytes to pdfDocument
* later in routine this firstDonorDoc pages are inserted not added
*/
let firstDonorPdfBytes = await fetch(url1).then(res => res.arrayBuffer());
await this.loadDataTodocument(firstDonorPdfBytes, sale, isWithData,
isEmptyForm).then(data => {
firstDonorPdfBytes = data;
});
/**
* load first document
*/
const firstDonorPdfDoc = await PDFDocument.load(firstDonorPdfBytes);
/**
* load url array convert to bytes, send bytes to populate textfields with
data
*/
for (let i = 0; i < urlArray.length; ++i) {
console.log(urlArray.length);
donorBytes[i] = await fetch(urlArray[i].url).then(res =>
res.arrayBuffer());
}
/* Insert data to donorBytes and create DonorBytesFinal array with data */
// tslint:disable-next-line:prefer-for-of
for (let i = 0; i < donorBytes.length; ++i) {
await this.loadDataTodocument(donorBytes[i], sale, isWithData,
isEmptyForm).then(data
=> {
donorBytesFInal.push(data);
});
}
// console.log(donorBytesFInal);
/*
convert donor bytes to PdfDocument after bytes include data re
donorBytesFInal
*/
for (let i = 0; i < donorBytesFInal.length; ++i) {
donorDoc[i] = await PDFDocument.load(donorBytesFInal[i]);
}
/* create out put document **/
const pdfDoc = await PDFDocument.create();
/**
* copay first page... not in array
*/
const [firstDonorPage] = await pdfDoc.copyPages(firstDonorPdfDoc, [0]);
/**
* copy all array pages of singular docuemnts output pdfdoc. Notices these
are insertpages nto addpage
*/
for (let i = 0; i < donorBytes.length; ++i) {
[donorPage[i]] = await pdfDoc.copyPages(donorDoc[i], [0]);
pdfDoc.insertPage(0, donorPage[i]);
}
/** first page is an ADDpage not an insert */
pdfDoc.addPage(firstDonorPage);
/** create tyes for 64 and 8 and update globally */
const u8 = await pdfDoc.save();
const n64 = await pdfDoc.saveAsBase64();
this.pdfService.changeUint8ByteArray(u8);
this.pdfService.changeBase64Array(n64);
const pdfBytes = u8;
/** redundant empty urlarray */
urlArray = [];
Upvotes: 0
Reputation: 33
The PDFDocument.load()
method will accept base64 strings as the parameter so you don't need to do transform those at all.
As for your variables storing url paths to pdf documents, you can use fetch instead of node's file system. As described in the pdf-lib docs, you can store the ArrayBuffer and pass that into PDFDocument.load()
like so:
const url = 'https://pdf-lib.js.org/assets/with_update_sections.pdf'
const arrayBuffer = await fetch(url).then(res => res.arrayBuffer())
const pdfDoc = await PDFDocument.load(arrayBuffer)
Upvotes: 2