Javascript 将图像转换为文件 return 零

Javascript convert image to File return zeros

我有来自其他服务器的 img

<img src="https://cloudserver/1.jpg">

单击此 img 我想转换为文件对象以向服务器发送 post 请求。 在这个函数之后我看到数据所有字节 = 0,不明白发生了什么?在搜索中我发现问题需要等待然后图像加载完成但我 100% 已经加载图像。

imgToFile: function (imageElement){
    imageElement.crossOrigin="anonymous";

    var canvasElement = document.createElement("canvas");
    canvasElement.width = imageElement.width;
    canvasElement.height = imageElement.height;
    var canvasContext = canvasElement.getContext("2d");
    canvasContext.drawImage(imageElement, 0, 0);

    var imageData = canvasContext.getImageData(0, 0, imageElement.width, imageElement.height).data;
    var buffer = new Uint8Array(imageData.length);
    for(var index = 0; index < imageData.length; index++)
        buffer[index] = imageData[index];

    var imageBlob = new Blob(buffer);
    return new File([imageBlob], /\/([^/]+)$/.exec(imageElement.src)[1]);
}

沙盒: https://liveweave.com/DCXuNY

这让我感到很惊讶,我以为我知道这部分规范,但结果是 since 2016,改变 crossorigin 属性状态是规范的一部分 img 的 relevant mutations, which will force a refetching of the image source.

Chrome 只赶上规格 relatively recently (M84),Firefox 仍然没有,因此只会抛出一个错误,抱怨图像确实污染了 canvas.

另一方面,

Chrome 将因此在您更改 crossOrigin IDL 属性后立即重新获取图像,这次使用适当的 CORS headers。因此,当您在该浏览器中点击 drawImage 时,它仍然不会获取符合 CORS 的资源(即使它是同一个文件,因为它由不同的 headers 提供,浏览器将完全获取它再次)。

与您的想法相反,您的图像仍未加载 Chrome。

要解决这个问题,您可以在您的 js 脚本中添加一个 onload 事件处理程序,但您还需要通过再次设置 src 强制为其他浏览器重新获取图像属性(即使是相同的值):

onload = (evt) => {
  const img = document.querySelector( 'img' );
  img.onload = (evt) => {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    ctx.drawImage(img,0,0);
    console.log(...ctx.getImageData(250,120,1,1).data);
  };
  img.crossOrigin = 'anonymous';
  img.src = img.src; // force refetching for non-Chrome browsers
};
img { width: 300px }
<img src="https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png">

但最好的办法当然是从一开始就使用正确的 CORS headers 直接请求您的图像,这样您就不会让您的用户白白下载同一个文件两次。

onload = (evt) => {
  const img = document.querySelector( 'img' );
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  ctx.drawImage(img,0,0);
  console.log(...ctx.getImageData(250,120,1,1).data);
};
img { width: 300px }
<img src="https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png" crossorigin="anonymous">