0

I'm in the midst of trying to create an spfx web part that will merge selected documents into one. I am using the pdf-lib and @pnp/sp libraries. Here is my code:

const mergedFile = await PDFDocument.create();

// Loop through each selected item
this.context.listView.selectedRows.forEach(async (row: RowAccessor) => {
   // Get the file array buffer
   const file = sp.web.getFileByServerRelativePath(row.getValueByName('FileRef'));
   const fileBytes: ArrayBuffer = await file.getBuffer();
   const fileToMerge = await PDFDocument.load(fileBytes);

   const copyPages = await mergedFile.copyPages(fileToMerge, fileToMerge.getPageIndices());
   copyPages.forEach((page) => {
     mergedFile.addPage(page);
   });
});


const savedMergedFile = await Promise.resolve(mergedFile.save());
const newFileAsBlob = new Blob([savedMergedFile]);
const newFile = await sp.web.getFolderByServerRelativePath(path).files.addChunked(encodeURI("newFile.pdf"), newFileAsBlob,  undefined, true);

I used this and this as reference to create my web part, but the problem is, when I run and test it, the resulting document is just a blank page. Could anyone shed light on why this is the result?

stm
  • 662
  • 1
  • 6
  • 23
whaleiam
  • 1
  • 2
  • @KJ right, I see what your saying, but my implementation is a for loop that loops through all files and appends the pages to the end of the document. The document itself is declared outside of the for loop. Do you think that this is where the issue lies? – whaleiam Aug 21 '23 at 15:12
  • @KJ yea, I ended up testing with 2,3,4 files and they all result in a singular blank page. I may be thinking it might have something to do with how the array is being converted to a blob object? – whaleiam Aug 21 '23 at 16:47
  • @KJ gotcha, so is there a way to fix this line const newFileAsBlob = new Blob([savedMergedFile]); such that it handles the conversion correctly? – whaleiam Aug 21 '23 at 17:25

1 Answers1

0

Ok, it took me a while, but I figured out that it wasn't actually the 'typecasting' to blob that was the issue. The issue was that the for loop was executing asynchronously from the rest of the function. This meant that the mergedFile.save() would execute before the for loop was able to copy the pages to the PDFDocument. Here is the answer in case anyone might ever need it.

const savedMergedFile = await this.createByteArray();
const fileAsBlob = new Blob([savedMergedFile])
const newFile = await sp.web.getFolderByServerRelativePath(path).files.addChunked(encodeURI(fileName), fileAsBlob, undefined, true)

private async createByteArray(): Promise<Uint8Array> {
    const mergedFile = await PDFDocument.create();

    for(const row of this.context.listView.selectedRows){
      const file = sp.web.getFileByServerRelativePath(row.getValueByName('FileRef'));
      const fileBytes: ArrayBuffer = await file.getBuffer();
      const fileToMerge = await PDFDocument.load(fileBytes);

      const copyPages = await mergedFile.copyPages(fileToMerge, fileToMerge.getPageIndices());
      copyPages.forEach((page) => {
        mergedFile.addPage(page);
      });
    }
    return mergedFile.save();
}
whaleiam
  • 1
  • 2