javascript - Javascript将图像转换为文件返回零
问题描述
我有来自其他服务器的 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]);
}
解决方案
这让我很惊讶,以为我知道这部分规范,但事实证明,自 2016 年以来,更改crossorigin
属性状态是 img相关突变的一部分,这将强制重新获取图像源。
Chrome最近才赶上了规格(M84),Firefox 仍然没有,因此只会抛出一个错误,抱怨图像确实污染了画布。
另一方面,Chrome 会在您更改crossOrigin
IDL 属性后立即重新获取图像,这次使用正确的 CORS 标头。因此,当您drawImage
在该浏览器中点击时,它仍然不会获取符合 CORS 的资源(即使它是同一个文件,因为它具有不同的标头,浏览器将再次完全获取它)。
因此,与您的想法相反,您的图像仍未加载到 Chrome 中。
要解决这个问题,您可以onload
在 js 脚本中添加一个事件处理程序,但您还需要通过再次设置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">
推荐阅读
- r - R找到有条件的正确名称
- c++ - 为什么 std::forward_list::empty 有 [[nodiscard]] 而 std::forward_list::max_size 没有?
- java - While 循环终止而不改变条件的值
- python - 确定 pandas 序列的元素是否包含不同序列的元素作为子字符串
- javascript - 如何从一个输入标签传递两个“名称”以在服务器中访问
- python - pandas 的 .query() 不接受我使用 like 'XXX%' 来表达 startwith 的表达
- cmake - 从 MSVC 2019 内置 CMake 配置英特尔编译器
- c# - 委托问题,名称在当前上下文中不存在?
- python - 仅从数据框中选择每个月的最后一周 - Python/Pandas
- llvm - 将现有函数的参数放在对 LLVM 函数传递中另一个函数的调用中