【问题标题】:What would cause an HTML5 canvas toBlob to create an incomplete image?什么会导致 HTML5 画布 toBlob 创建不完整的图像?
【发布时间】:2017-11-03 00:53:43
【问题描述】:

我有以下 javascript 从画布生成图像并将它们上传到服务器。

var can = document.createElement('canvas');
can.width = 600;
can.height = 600;
var ctx = can.getContext('2d');
ctx.fillRect(0, 0, can.width, can.height);
ctx.fillText("Julia", can.width/2, can.height/2);
can.toBlob(uploadImage, "image/jpg", 0.9);

function uploadImage(jpeg) {
  var data = new FormData();
  data.append('image', jpeg, 'image.jpg');
  ...
}

每隔一段时间,结果就会像上面那样,只是部分绘制。多个画布按顺序处理和上传,仅在 ajax 完成时继续进行(在 ... 部分),因此一次只能处理一个。

你见过这种情况吗?如果是这样,在这个过程中我应该在哪里进一步调试?可能是上下文对象中的设置或其他内容?

编辑

上传是一个 ajax 帖子,其承诺仅在成功分支上解决。它实际上使用了 Angular 的 $http 服务:

$http({method: 'POST', url: '...', data: data}).then(function(response) {
    // callback that processes and uploads the next image
});

【问题讨论】:

  • 在我看来,图片上传已中断,您只有部分图片。我从未见过 toBlob 或 toDataURL 对图像执行此操作,但我看到很多不完整的 jpeg 在由于连接失败而关闭和上传时看起来像这样
  • 你能显示上传的代码吗?
  • 那么如果服务器没有读取整个请求,javascript 是否有可能看到成功路径?...我认为不会,但也许这是一个角度问题。也许是服务器上的一个简单缓冲问题...也许我可以将 blob 大小作为另一个表单参数传递,并根据服务器上接收到的文件大小检查它。
  • @RyanCalhoun 是的,这听起来是个好主意。如果您无法轻松重现,您肯定需要进行更多日志记录以找出损坏发生的位置
  • 嗨@RyanCalhoun 你检查我的答案了吗,有帮助吗

标签: javascript google-chrome html5-canvas chromium form-data


【解决方案1】:

除了画布部分外,我们面临着类似的情况。你可以简单地调试它。

  1. 将给定的 blob 作为 img src 打印到页面,以确保该文件已正确创建。还打印 blob 大小。
  2. 打开浏览器的开发者工具 -> 网络 -> 过滤 XHR 并开始上传
  3. 分配完成(状态 200)ajax 请求并查看请求标头 -> 内容长度。如果此数字等于页面上的 blob 大小,则它已正确上传并在服务器端发现问题。否则检查 ajax 调用。
  4. 确保服务器已设置适合您的用例的最大客户端请求大小。例如 nginx 的默认值为 1M。

提示:通过 $http 标头中的 blob.type 设置 Content-Type。 POST 的默认值为 application/json。

【讨论】:

  • 或者更好,不要通过devtools做,而是让服务器响应上传文件的大小,并在客户端进行比较以检查是否顺利。
  • 您遇到了什么问题,您解决了吗?是客户端没有发送图像还是服务器没有接收到它?
  • 是的。我们做到了。但我使用了github.com/danialfarid/ng-file-upload。它为媒体文件提供了一些有用的功能,如调整大小、进度等。我们还处理了分块为 10M 部分的大型视频文件,所以第一次是 nginx 的 max_request_body_size 削减了我们的请求。然后是后端阅读器(python)逻辑中的一个错误。但我们也实现了暂停和恢复等功能,所以情况略有不同。上面的调试步骤应该对所有这些问题都是通用的 + 双方的日志记录总是显示出了什么问题..
【解决方案2】:

尝试重新安排你的逻辑,你在上传过程中得到了赛车条件,当图像被创建时,它们必须在回调排序中被回调..

// ...
ctx.fillText("Julia", can.width / 2, can.height / 2);
can.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;
        // we have image out of canvas and now do the upload of newImg
        // $http || $.ajax call goes here
    };
});

如果您想提交图像数据 URL,请尝试类似,,

// ...
ctx.fillText("Julia", can.width / 2, can.height / 2);
can.toBlob(function(blob) {
    var reader = new window.FileReader();
    reader.readAsDataURL(blob); 
    reader.onloadend = function() {
                base64data = reader.result;
        // we have image in base64 and now do the upload of base64data
        // $http || $.ajax call goes here
    }
});

hth, k

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-17
    • 2014-08-15
    • 1970-01-01
    • 1970-01-01
    • 2018-07-22
    • 2021-12-14
    • 1970-01-01
    • 2011-05-09
    相关资源
    最近更新 更多