在将 blob 提交到服务器之前等待 canvas.toDataURL() 完成

Waiting for canvas.toDataURL() to complete before submitting blob to server

我这里有一个项目需求,使用文件输入接受文件并显示在canvas上,同时将其作为blob处理并发送到后端进行处理。根据文件类型,我会使用不同的进程。

如果文件类型为pdf,则使用pdf.js进行处理,pdf图片会显示在canvas上,同时将文件转换为blob发送到后端进行处理。到目前为止,这仅适用于单页 pdf,因为我可以直接将 canvas 数据放入 blob 并在 toDataURL 完成后直接发送。

但是对于多页 pdf,我在每页上执行多个 toDataURL 运行 时遇到了问题。我的想法是,当我使用 pdf.js 的 getPage 迭代每个页面时,我将在 canvas 上显示该页面,并将 canvas 图像作为一个 blob 并将其推送到一个大批。处理完所有页面并将所有 blob 推入数组后,我会将其发送到后端进行处理。

var __TOTAL_PAGES, __ISMULTIPLEPAGE, __CANVAS = undefined;
var __MULTIPAGEHOLDER = [];

function showPDF(pdf_url) {
    PDFJS.getDocument({url: pdf_url}).then(function (pdf_doc) {
        __TOTAL_PAGES = pdf_doc.numPages;
        __ISMULTIPLEPAGE = __TOTAL_PAGES > 1 ? true : false;

        // Show the first page
        for (var i = 0; i < __TOTAL_PAGES; i++){
            $('#parentId').append('<canvas id="canvas-'+(i+1)+'"></canvas>');

            showPage(i+1);
    }

    }).catch(function (error) {
    /* Insert any error handling here */
    });
}

function showPage(page_no) {
    __PDF_DOC.getPage(page_no).then(function (page) {
        /* Some setup here */

        var renderContext = {
            canvasContext: /* Some value */,
            viewport: /* Some value */
        };

        // Render the page contents in the canvas
        page.render(renderContext).then(function () {

            __CANVAS = document.getElementById('canvas-'+page_no);

            // $('#go_pdf').click();
            if (__ISMULTIPLEPAGE){
                var thisPageURL = __CANVAS.toDataURL();
                    thisPage = dataURLtoBlob(thisPageURL);
                    __MULTIPAGEHOLDER.push(thisPage);

                if (__MULTIPAGEHOLDER.length === __TOTAL_PAGES){
                    // Once all blob are ready then only will submit to backend
                    submitPDFtoBackend(__MULTIPAGEHOLDER);
                }
            } else {
                var pdfData = [];
                if (pdfCanvas != null) {
                    var data = __CANVAS.toDataURL();
                    pdfData.push(dataURLtoBlob(data));
                }

                submitPDFtoBackend(pdfData);
            }
        });
    });
}

但是上面的方法并没有达到我的预期,因为有时,即使 toDataURL 仍然是 运行ning,submitPDFtoBackend 方法仍然会被调用。我只想在完成所有 toDataURL 并且所有 blob 都已推送到数组后才调用 submitPDFtoBackend。

我读过有关将 toDataURL 进程作为承诺的信息,因此可以使用 $.when 在承诺上执行提交方法,但我不确定这是否可行。像

$.when.apply(null, promise).then(function() {
    submitPDFtoBackend(__MULTIPAGEHOLDER);
});

但我不确定该怎么做。

谢谢

  1. 您可以通过 canvas.toBlob
  2. 直接转到 blob,而不是转到 dateURL 然后从那里转到 blob
  3. 要检查 blob 是否准备就绪,您可以将其捕获在 img 元素的 onload 处理程序中,然后在 onload 处理程序中调用 submitPDFToBackend。下面的片段直接来自 mdn

var canvas = document.getElementById('canvas');

canvas.toBlob(function(blob) {
var newImg = document.createElement('img'),
url = URL.createObjectURL(blob);
newImg.onload = function() {
// no longer need to read the blob so it's revoked
URL.revokeObjectURL(url);
};
newImg.src = url;
document.body.appendChild(newImg);

});