使用 Cropper.js 将 Canvas 转换为 Blob

8
我使用 cropper.js 创建了一个应用程序来裁剪图像。应用程序可以正常工作并裁剪图像,之后我尝试将裁剪后的图像作为blob发送到服务器进行存储。
根据cropper.js文档,我们可以使用canvas.toDataURL获取数据URL,或使用canvas.toBlob获取blob并使用FormData上传到服务器。当我尝试使用canvas.toDataURL()时,我得到了base64字符串,但实际上我需要以blob形式发送文件,所以我尝试使用canvas.toBlob(),但在Chrome中出现了Uncaught TypeError: canvas.toBlob is not a function,在Firefox中出现了TypeError: Not enough arguments to HTMLCanvasElement.toBlob. 请问有人能告诉我解决方法吗?
我的代码如下:
var canvas = $image.cropper("getCroppedCanvas", undefined);
var formData = new FormData();
formData.append('mainImage', $("#inputImage")[0].files[0]);
formData.append('croppedImage', canvas.toBlob());
2个回答

9

toBlob 方法是异步的,需要两个参数:回调函数和图像类型(第三个可选参数是质量):

void canvas.toBlob(callback, type, encoderOptions);

示例

if (typeof canvas.toBlob !== "undefined") {
  canvas.toBlob(function(blob) {
      // send the blob to server etc.
      ...
  }, "image/jpeg", 0.75);
}
else if (typeof canvas.msToBlob !== "undefined") {
  var blob = canvas.msToBlob()
  // send blob
}
else {
  // manually convert Data-URI to Blob (if no polyfill)
}

并非所有浏览器都支持它(IE需要前缀msToBlob,并且其工作方式与标准不同),而Chrome需要一个polyfill

更新对于已被删除的OP编辑)裁剪后的图像之所以较大,主要原因是原始图片为JPEG格式,新图片为PNG格式。您可以使用toDataURL来更改此设置:

var uri = canvas.toDataURL("image/jpeg", 0.7);  // last=quality

在将数据传递给手动的data-uri转换为Blob之前,我建议使用polyfill。如果浏览器支持toBlob(),那么使用它会比通过编码data-uri更快且占用更少的内存开销。


我需要为Chrome和IE做什么? - Alex Man
@AlexMan 只需在 Chrome 中包含我提供的 polyfill。在 IE 中,您应该能够使用 canvas.msToBlob(...)。请注意,msToBlob 的工作方式与标准略有不同,因此建议在此处也使用 polyfill。 - user1693593
@AlexMan 添加了 MS 版本的示例(未经测试)。 - user1693593
@AlexMan 注意,您不能将Blob附加到DOM /表单中。它必须表示为字符串(即数据URI)。您可以将Blob存储为全局变量,并将其传递给用于将数据发送到服务器的方法。 - user1693593
@AlexMan,那将是一个不同的问题。我建议您为此打开一个新问题,因为这里的原始问题是,如果我理解正确,如何使用toBlob()方法。 - user1693593

5

正确的使用方法: https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement/toBlob

你需要传递回调函数并在回调函数中使用blob对象。 toBlob() 不会返回blob,而是接受一个回调函数,并将 blob 作为参数提供。

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);
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接