【问题标题】:Javascript convert image to File return zerosJavascript将图像转换为文件返回零
【发布时间】:2020-09-18 14:13:48
【问题描述】:

我有来自其他服务器的 img

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

单击此 img 我想转换为 File 对象以向服务器发送 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

【问题讨论】:

  • 请分享一个工作示例,展示如何调用所有方法。很奇怪你有零,你应该只有一个错误,因为设置crossOrigin不会使图像重新获取资源,这意味着你应该通过绘制这个图像来污染你的画布,并且你不应该在@之后到达任何东西987654325@.
  • 嗨,我添加了沙盒

标签: javascript canvas html5-canvas blob fileapi


【解决方案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 }
&lt;img src="https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png"&gt;

但最好的方法当然是从一开始就使用正确的 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 }
&lt;img src="https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png" crossorigin="anonymous"&gt;

【讨论】:

  • 哇!它的核心知识:) 我尝试使用第二个变体,现在所有工作都无需双重下载。谢谢!附言有趣的是为什么在问题变体中我没有在 chrome 网络选项卡中观看第二次下载?
  • 关于最后评论我想通了:)
猜你喜欢
  • 2015-10-11
  • 1970-01-01
  • 2016-02-14
  • 1970-01-01
  • 1970-01-01
  • 2017-10-09
  • 2023-03-23
  • 1970-01-01
  • 2020-11-12
相关资源
最近更新 更多