Javascript将图像转换为文件返回零

问题描述 投票:0回答:1

我有来自其他服务器的img

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

在单击此img时,我想转换为File对象,以向服务器发送发布请求。在执行此功能后,我看到所有字节的数据都为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

javascript canvas html5-canvas blob fileapi
1个回答
1
投票

对于我以为我知道这部分规格的人感到非常惊讶,但是事实证明,更改since 2016属性状态是crossorigin属性状态的一部分。img的relevant mutations,将强制输入refetching of the image source

Chrome仅赶上规格relatively recently(M84),Firefox仍然没有,因此会抱怨图像确实弄脏了画布,并抛出错误消息。

另一方面,Chrome会在您更改crossOrigin IDL属性后立即重新获取图像,这次使用正确的CORS标头。因此,当您在该浏览器中点击drawImage时,它仍不会获取符合CORS的资源(即使它是同一文件,因为它带有不同的标头,浏览器也会再次完全获取它)。

与您的想法相反,您的图像仍未加载到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标头直接请求您的图像,因此,您不会让用户下载相同文件的两倍而不花钱。

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">
© www.soinside.com 2019 - 2024. All rights reserved.