我的代码在我的localhost上工作得非常好,但它不能在网站上运行。
我从控制台收到此错误,此行.getImageData(x,y,1,1).data
:
Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The canvas has been tainted by cross-origin data.
我的部分代码:
jQuery.Event.prototype.rgb=function(){
var x = this.offsetX || (this.pageX - $(this.target).offset().left),y = this.offsetY || (this.pageY - $(this.target).offset().top);
if (this.target.nodeName!=="CANVAS")return null;
return this.target.getContext('2d').getImageData(x,y,1,1).data;
}
注意:我的图片网址(src)来自子网址
答案 0 :(得分:85)
正如其他人所说,你已经"污染"通过从交叉起源域加载画布。
https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image
但是,您可以通过简单地设置:
来防止这种情况发生img.crossOrigin = "Anonymous";
仅当远程服务器正确设置以下标头时才有效:
Access-Control-Allow-Origin "*"
Dropbox file chooser使用"直接链接"选项就是一个很好的例子。我在oddprints.com上使用它将远程保管箱图像网址中的图像保存到我的画布中,然后将图像数据提交回我的服务器。全部用javascript
答案 1 :(得分:34)
我发现我必须使用.setAttribute('crossOrigin', '')
并且必须在URL的查询字符串中附加时间戳,以避免缺少Access-Control-Allow-Origin
标头的304响应。
这给了我
var url = 'http://lorempixel.com/g/400/200/';
var imgObj = new Image();
imgObj.src = url + '?' + new Date().getTime();
imgObj.setAttribute('crossOrigin', '');
答案 2 :(得分:17)
您将无法直接从其他服务器将图像绘制到画布中,然后使用getImageData
。这是一个安全问题,画布将被视为“污点”。
您是否可以使用PHP将图像副本保存到服务器,然后只加载新图像?例如,您可以将URL发送到PHP脚本并将其保存到您的服务器,然后将新文件名返回到您的javascript,如下所示:
<?php //The name of this file in this example is imgdata.php
$url=$_GET['url'];
$img = file_get_contents($url);
$fn = substr(strrchr($url, "/"), 1);
file_put_contents($fn,$img);
echo $fn;
?>
你可以使用PHP脚本和一些像这样的ajax javascript:
xi=new XMLHttpRequest();
xi.open("GET","imgdata.php?url="+yourImageURL,true);
xi.send();
xi.onreadystatechange=function() {
if(xi.readyState==4 && xi.status==200) {
img=new Image;
img.onload=function(){
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
}
img.src=xi.responseText;
}
}
如果在此之后在画布上使用getImageData
,它将正常工作。
或者,如果您不想保存整个图像,可以传递x&amp; y坐标到PHP脚本并计算该侧的像素rgba值。我认为在PHP中进行这种图像处理有很好的库。
如果您想使用此方法,请告诉我您是否需要帮助实施它。
编辑:peeps指出php脚本已暴露并允许互联网恶意使用它。有一百万种方法可以解决这个问题,其中一种最简单的方法是某种URL混淆...我认为安全的PHP实践值得一个单独的谷歌; P
答案 3 :(得分:2)
您的问题是您加载外部图片,意味着从另一个域。当您尝试访问画布上下文的任何数据时,这会导致安全性错误。
答案 4 :(得分:2)
您通过从跨源域加载来“污染”画布。看看这篇MDN文章:
https://developer.mozilla.org/en-US/docs/HTML/CORS_Enabled_Image
答案 5 :(得分:2)
在本地测试代码时,我在Chrome
上看到此错误。我切换到Firefox
,但再也看不到错误了。也许切换到其他浏览器是一种快速解决方案。
如果您使用的是第一个答案中给出的解决方案,请确保在声明img.crossOrigin = "Anonymous";
变量之后添加img
(例如var img = new Image();
)。
答案 6 :(得分:0)
正如亚光烧伤在his answer中所说,您可能需要在托管问题图像的服务器上启用CORS。
如果服务器是Apache,可以通过将以下代码段(从here)添加到VirtualHost配置或.htaccess
文件来完成此操作:
<IfModule mod_setenvif.c>
<IfModule mod_headers.c>
<FilesMatch "\.(cur|gif|ico|jpe?g|png|svgz?|webp)$">
SetEnvIf Origin ":" IS_CORS
Header set Access-Control-Allow-Origin "*" env=IS_CORS
</FilesMatch>
</IfModule>
</IfModule>
...如果将其添加到VirtualHost,您可能也需要重新加载Apache的配置(例如。sudo service apache2 reload
如果Apache在Linux服务器上运行)< / p>
答案 7 :(得分:0)
在本地工作时,我遇到了类似的问题。您的网址将成为本地文件的路径,例如文件:///Users/PeterP/Desktop/folder/index.html。
请注意,我在使用MAC。
我通过全局安装http-server来解决这个问题。 https://www.npmjs.com/package/http-server
步骤:
npm install http-server -g
http-server ~/Desktop/folder/
PS:我假设您已经安装了节点,否则您将无法获得运行得很远的npm命令。
答案 8 :(得分:0)
我(非常简单)使用https://www.base64-image.de/将我的图片转换为基本的64个文件。然后,我只是用该(非常长的)图像代码字符串替换了对文件路径的调用。
答案 9 :(得分:0)
我的问题太混乱了,我只对图像进行了base64编码,以确保不会出现任何CORS问题
答案 10 :(得分:0)
您可以使用图像源而不是实际图像源将图像转换为数据字符串。
[https://www.base64-image.de/][1] 将图像转换为数据字符串。
从上述网站转换和复制字符串数据。
设置 image.src =
答案 11 :(得分:0)
解决方法, 将源图像 URL 转换为 Base64 数据并分配给 img
例如,使用 Axios
const getBase64 = async(url)=>{
try {
let image = await axios.get(url, { responseType: 'arraybuffer' });
let raw = Buffer.from(image.data).toString('base64');
return "data:" + image.headers["content-type"] + ";base64,"+raw;
} catch (error) {
console.log(error)
}
}
var image = new Image()
image.src=getBase64(url)
没有来自画布的跨源依赖
答案 12 :(得分:-1)
我今天遇到同样的问题,并按照以下代码解决。
html代码:
<div style='display: none'>
<img id='img' src='img/iak.png' width='600' height='400' />
</div>
<canvas id='iak'>broswer don't support canvas</canvas>
js code:
var canvas = document.getElementById('iak')
var iakImg = document.getElementById('img')
var ctx = canvas.getContext('2d')
var image = new Image()
image.src=iakImg.src
image.onload = function () {
ctx.drawImage(image,0,0)
var data = ctx.getImageData(0,0,600,400)
}
代码如上所述,并且没有跨域问题。
答案 13 :(得分:-2)
我遇到了同样的问题,对我来说,只需将https:${image.getAttribute('src')}
串联起来就可以了