1

I tried searching a lot for this issue but did not get anything that helps me.

I am trying to download a bunch of pdf files from Strapi using URL and after downloading every pdf I am pushing it into a folder to create a zip.

My issue is while downloading, few of the files are not able to push in zip folder because of large file size. Basically, zip creation is not waiting to complete the download.

Here is my code, I am using map() to get URLs and using blob() to download it and then used zip to save it in the zip folder.

const downloadPdf = async (newData: any) => {
  return new Promise(async (resolve) => {
    let PolicyDocData: any;
    [...some operation...]
    if (newData.laws) {
      if (newData.laws.description[0]) {
        [...some operation to create an array for URL...]
        let lawDoc = Array.from(new Set(lawDocArray));
        lawDoc.map(async (val: any, index: any) => {
          const lawUrl = val.url.slice(1);
          const DocUrl = serverUrl + lawUrl;
          let download = await fetch(DocUrl, {
            method: "GET",
          }).then((response) => response.blob()).then((response) => {
            let fileType = ".pdf";
            const timeStamp = Math.floor(Date.now() / 1000);
            const fileName = val.name;
            let docFileName = fileName + "_" + timeStamp;
            zip.folder("Compliance/Laws").file(docFileName + fileType, response);
          })
          if (lawDoc.length - 1 === index) {
            resolve(Contents);
          }
        })
      }
    }
  }).then((Contents: any) => {
    if (Contents) {
      Packer.toBlob(PolicyDocumentCreator(Contents)).then((blob) => {
        zip.generateAsync({ type: "blob" }).then(function (content: any) {
          saveAs(content, folderName ? folderName : complianceName + ".zip");
          setLoading(false);
        })
      });
    }
  });
};

I tried to solve it using setTimeout() but this is not a feasible solution.

Jay
  • 329
  • 2
  • 12
  • Why are you not putting zipping the folder in a `then` once the download is done? something like this: Promise.all().then() – Gilad Shnoor Dec 09 '20 at 08:06
  • Yeah, I tried as you suggested, but facing the same issue again. @GiladShnoor – Jay Dec 09 '20 at 09:14
  • `new Promise(async function (resolve, reject) { resolve(content) });` is completely pointless, what were you trying to achieve with that? – Bergi Dec 09 '20 at 09:36
  • Don't pass `async` functions as callbacks to `then`! If you want to use `async`/`await`, you shouldn't need `then` at all - use `await` instead. – Bergi Dec 09 '20 at 09:38
  • `if (lawDoc.length - 1 === index) { resolve(Contents); }` looks suspiciously like the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it). You're probably looking for `Promise.all`?! – Bergi Dec 09 '20 at 09:39
  • @Bergi I have removed `async` and `new Promise(async function (resolve, reject) { resolve(content) });` but I am still on same page. (edited my question) – Jay Dec 09 '20 at 10:28
  • @Jayant can you please edit the question to include the Promise.all code so I can try and figure out why it's failing – Gilad Shnoor Dec 09 '20 at 11:45
  • @GiladShnoor here it is. i have included the Promise and whole steps to downloading it. – Jay Dec 09 '20 at 13:29

1 Answers1

0

Finally, I got the solution and I am posting here if anyone looking for it. I break my whole function into two different functions and used Async/await and Promise.all()

Like this:

const downloadPdf = async (newData: any) => {
  if (newData.laws) {
    if (newData.laws.description[0]) {
      [...Few operation to create an array of URLs...]
      let lawDoc = Array.from(new Set(lawDocArray));
      const val: any = await downloadAllLawPdf(lawDoc);
    }
  }
  if (Contents) {
    const blob = await Packer.toBlob(PolicyDocumentCreator(Contents));
    const content: any = await zip.generateAsync({ type: "blob" });
    saveAs(content, folderName ? folderName : complianceName + ".zip");
    setLoading(false);
  }
};

and then use a function downloadAllLawPdf() to download and wait till download gets completed and return the response.

const downloadAllLawPdf = async (lawDoc: any) => {
  return Promise.all(lawDoc.map(async (val: any, index: any) => {
    const lawUrl = val.url.slice(1);
    const DocUrl = serverUrl + lawUrl;
    let docFileName = ''
    let fileType = ".pdf";
    const res = await fetch(DocUrl, {
      method: "GET",
    });
    const response = await res.blob();
    const timeStamp = Math.floor(Date.now() / 1000);
    const fileName = val.name;
    docFileName = fileName + "_" + timeStamp;
    zip.folder("Compliance/Laws").file(docFileName + fileType, response);
  }));
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Jay
  • 329
  • 2
  • 12