【问题标题】:Creating multiple pdfs with pdf2htmljs使用 pdf2htmljs 创建多个 pdf
【发布时间】:2020-06-05 14:13:57
【问题描述】:

我编写了以下代码来使用 html2pdf.js 创建几个 pdf 文件。稍后我想将它们保存到存档并下载所述存档。我正在使用 jsZip 创建和填充存档并使用 fileSaver 来保存它:

window.zip = new JSZip();
let masterDiv = document.createElement('div');
masterDiv.id = 'masterDiv';
document.body.appendChild(masterDiv);

// Stundenplan für jeden Kandidaten erstellen
for (let i = 0; i < window.allCandidates.length; i++) {
  let candidate = window.allCandidates[i].split(',');
  window.lastName = candidate[0];
  window.firstName = candidate[1];
  window.filter = 'candidate';
  setScheduleView('masterDiv');

  let worker = html2pdf();

  let opt = {
    margin: 1,
    image: {
      type: 'jpeg',
      quality: 1
    },
    html2canvas: {
      scale: 2
    },
    jsPDF: {
      unit: 'mm',
      format: 'A3',
      orientation: 'portrait'
    }
  };

  // PDF erstellen
  worker.set(opt).from(masterDiv).outputPdf().then((pdf) => {
    window.zip.file(window.lastName + '.' + window.firstName + '.pdf', pdf, {
      binary: true
    });
  });

  setTimeout(() => {
    clearDiv(masterDiv);
    worker = null;
  }, 50);
}

setTimeout(() => {
  window.zip.generateAsync({
    type: "blob"
  }).then(function(content) {
    saveAs(content, "allPDFs.zip");
  });
}, 2000);

我现在的问题是:不是每个循环一个 pdf,而是一个包含完整内容的 pdf。为了让 html2pdf.js 明白它应该为每个循环创建一个新的 pdf 文件,我需要进行哪些更改?

【问题讨论】:

  • 我对库不熟悉,但我想你应该在循环中运行window.zip.generateAsync。您是否还在使用计时器等待异步调用?如果是这样,那么您也应该更改它,因为您永远不知道生成 pdf 需要多长时间。

标签: javascript html2pdf


【解决方案1】:

您似乎没有正确等待异步操作完成,特别是清除 div 的操作可能在生成 pdf 之前执行,并且在生成 zip 时也会发生同样的情况,您在这里有几个选项,具体取决于如何您要处理 pdf:

与 async/await 密切相关:

// ...
async function generatePDFs(){
    for (let cand of window.allCandidates) {
        let candidate = cand.split(',');
        // ...
        // wait for every worker to finish before the next iterarion
        await worker.set(opt).from(masterDiv).outputPdf().then((pdf) => {
            window.zip.file(window.lastName + '.' + window.firstName + '.pdf', pdf, {
                binary: true
            });
            clearDiv(masterDiv);
        });
    }

    window.zip.generateAsync({
        type: "blob"
    }).then(function (content) {
        saveAs(content, "allPDFs.zip");
    });
}

与 reduce 密切相关:以防您无法使用 async/await

// create an array of functions so that each one of them will
// generate the pdf for a candidate  and then clear the div.
let pdfGenerators = allCandidates.map((cand) => {
    return () => {
        let candidate = cand.split(',');
        // ...
        return worker.set(opt).from(masterDiv).outputPdf().then((pdf) => {
            window.zip.file(window.lastName + '.' + window.firstName + '.pdf', pdf, {
                binary: true
            });
            clearDiv(masterDiv);
        });
    }
});
// call reduce on your pdf generators array starting from a resolved promise, so
// everytime a  promise is resolved you enqueue the next one, after that generate the 
// zip
pdfGenerators.reduce((pre, curr) => pre.then(curr), Promise.resolve()).then(() => {
    window.zip.generateAsync({
        type: "blob"
    }).then(function (content) {
        saveAs(content, "allPDFs.zip");
    })
});

与 Promise.all 并行:对于这种方法(并且通常)停止使用全局变量,而是创建一个函数来声明生成 PDF 需要读取的所有内容: p>

// ...
function generatePDF(candidate, i){
    let div = document.createElement('div');
    div.id = `candidate-${i}`;
    document.body.append(div);
    setScheduleView(div.id);
    let [lastName, firstName] = candidate.split(',');
    // ...
    return worker.set(opt).from(div).outputPdf().then((pdf) => {
        window.zip.file(lastName + '.' + firstName + '.pdf', pdf, {
            binary: true
        });
        clearDiv(div);
    });
}
// wait for all pdfs to be generated (in parallel)
Promise.all(allCandidates.map(generatePDF)).then(() => {
    window.zip.generateAsync({
        type: "blob"
    }).then(function (content) {
        saveAs(content, "allPDFs.zip");
    });
});

为了正确处理 JS 中的异步编程,请阅读 PromisesAsync functions

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-19
    • 2022-11-10
    • 1970-01-01
    • 1970-01-01
    • 2017-06-28
    • 2012-07-03
    相关资源
    最近更新 更多