为什么canvas.toDataURL()会抛出安全异常?

时间:2010-03-05 22:00:18

标签: javascript html5 canvas cross-domain

我睡眠不足或者什么?以下代码

var frame=document.getElementById("viewer");
frame.width=100;
frame.height=100;

var ctx=frame.getContext("2d");
var img=new Image();
img.src="http://www.ansearch.com/images/interface/item/small/image.png"

img.onload=function() {
    // draw image
    ctx.drawImage(img, 0, 0)

    // Here's where the error happens:
    window.open(frame.toDataURL("image/png"));
}

抛出此错误:

SECURITY_ERR: DOM Exception 18

这不可能不起作用!有人可以解释一下吗?

10 个答案:

答案 0 :(得分:67)

specs中说:

  

每当toDataURL()方法一个   canvas元素,其起源 - 清洁标志   被调用设置为false的方法   必须提出SECURITY_ERR例外。

如果图像来自另一台服务器,我认为你不能使用toDataURL()

答案 1 :(得分:17)

在为我工作的图像对象上设置交叉原点属性(我使用的是fabricjs)

    var c = document.createElement("img");
    c.onload=function(){
        // add the image to canvas or whatnot
        c=c.onload=null
    };
    c.setAttribute('crossOrigin','anonymous');
    c.src='http://google.com/cat.png';

对于那些使用fabricjs的人,这里是如何修补Image.fromUrl

// patch fabric for cross domain image jazz
fabric.Image.fromURL=function(d,f,e){
    var c=fabric.document.createElement("img");
    c.onload=function(){
        if(f){f(new fabric.Image(c,e))}
        c=c.onload=null
    };
    c.setAttribute('crossOrigin','anonymous');
    c.src=d;
};

答案 2 :(得分:16)

如果映像托管在设置Access-Control-Allow-Origin或Access-Control-Allow-Credentials之一的主机上,则可以使用跨源资源共享(CORS)。 See here (the crossorigin attribute) for more details.

您的另一个选择是让您的服务器拥有一个获取和提供图像的端点。 (例如http://your_host/endpoint?url=URL) 这种方法的缺点是延迟和理论上不必要的提取。

如果有更多备用解决方案,我有兴趣了解它们。

答案 3 :(得分:13)

似乎有一种方法可以防止,如果图​​像托管能够为图像资源提供以下HTTP标头,并且浏览器支持CORS:

access-control-allow-origin: *
access-control-allow-credentials: true

此处说明:http://www.w3.org/TR/cors/#use-cases

答案 4 :(得分:2)

我遇到了同样的问题,并且所有图片都托管在同一个域中......所以,如果有人遇到同样的问题,我的解决方法就是这样:

我有两个按钮:一个用于生成画布,另一个用于从画布生成图像。当我在第一个按钮上写下所有代码时,它只对我有用,对不起,我不知道为什么。所以当我点击它的同时生成画布和图像......

当代码在不同的函数上时,我总是遇到这个安全问题... = /

答案 5 :(得分:2)

我能够使用它来使它工作:

将此内容写在源服务器上.htaccess的第一行

Header add Access-Control-Allow-Origin "*"

然后在创建<img>元素时,按以下步骤操作:

// jQuery
var img = $('<img src="http://your_server/img.png" crossOrigin="anonymous">')[0]

// or pure
var img = document.createElement('img');
img.src='http://your_server/img.png';
img.setAttribute('crossOrigin','anonymous');

答案 6 :(得分:2)

最后我找到了解决方案。只需要在crossOrigin func

中添加fromURL作为第三个参数
fabric.Image.fromURL(imageUrl, function (image) {
            //your logic
    }, { crossOrigin: "Anonymous" });

答案 7 :(得分:1)

您不能在ID中添加空格

<强>更新

我的猜测是,图像位于与执行脚本不同的服务器上。我在自己的页面上运行它时能够复制你的错误,但是当我使用同一域上托管的图像时,它工作正常。所以它与安全相关 - 将图像放在您的网站上。任何人都知道为什么会这样吗?

答案 8 :(得分:0)

如果您只是在画布上绘制一些图像,请确保您正在加载来自同一域的图像。

www.example.com example.com不同

因此,请确保您的地址栏中的图片和网址是否相同,无论是否为www。

答案 9 :(得分:0)

我使用fabric.js并且可以使用toDatalessJSON而不是toDataURL解决此问题:

canvas.toDatalessJSON({ format: 'jpeg' }).objects[0].src

编辑:没关系。这导致只有背景图像被导出到JPG,没有绘图在顶部,所以它毕竟不是完全有用。