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

时间:2022-11-21 08:49:46

Did I not get enough sleep or what? This following code

我睡眠不足吗?这个代码

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"));
}

is throwing this error:

把这个错误:

SECURITY_ERR: DOM Exception 18

There's no way this shouldn't work! Can anyone explain this, please?

这是不可能的!有人能解释一下吗?

10 个解决方案

#1


67  

In the specs it says:

在说明书中,它说:

Whenever the toDataURL() method of a canvas element whose origin-clean flag is set to false is called, the method must raise a SECURITY_ERR exception.

只要调用了一个画布元素的toDataURL()方法,它的原clean标志被设置为false,那么该方法就必须抛出SECURITY_ERR异常。

If the image is coming from another server I don't think you can use toDataURL()

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

#2


17  

Setting cross origin attribute on the image objects worked for me (i was using fabricjs)

为我工作的图像对象设置跨源属性(我使用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';

For those using fabricjs, here's how to patch Image.fromUrl

对于那些使用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;
};

#3


16  

If the image is hosted on a host that sets either of Access-Control-Allow-Origin or Access-Control-Allow-Credentials, you can use Cross Origin Resource Sharing (CORS). See here (the crossorigin attribute) for more details.

如果该映像驻留在一个主机上,该主机设置了访问控制允许源或访问控制允许凭证,那么您可以使用跨源资源共享(CORS)。有关更多细节,请参见这里(crossorigin属性)。

Your other option is for your server to have an endpoint that fetches and serves an image. (eg. http://your_host/endpoint?url=URL) The downside of that approach being latency and theoretically unnecessary fetching.

您的另一个选项是您的服务器具有一个获取和服务图像的端点。(如。该方法的缺点是延迟和理论上不必要的抓取。

If there are more alternate solutions, I'd be interested in hearing about them.

如果有更多的替代解决方案,我很有兴趣听听他们的意见。

#4


13  

Seems there is a way to prevent that if image hosting able to provide the following HTTP headers for the image resources and browser supports CORS:

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

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

It is stated here: http://www.w3.org/TR/cors/#use-cases

这里有:http://www.w3.org/TR/cors/#用例。

#5


2  

I had the same problem and all the images are hosted in the same domain... So, if someone is having the same problem, here is how I solved:

我有同样的问题,所有的图片都在同一个域名中…所以,如果有人有同样的问题,我是这样解决的:

I had two buttons: one to generate the canvas and another one to generate the image from the canvas. It only worked for me, and sorry that I don't know why, when I wrote all the code on the first button. So when I click it generate the canvas and the image at the same time...

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

I always have this security problem when the codes were on different functions... =/

我总是有这样的安全问题当代码在不同的功能上…= /

#6


2  

Finally i found the solution. Just need add the crossOrigin as third param in fromURL func

最后我找到了解决方案。只需在fromURL func中添加第三个param。

fabric.Image.fromURL(imageUrl, function (image) {
            //your logic
    }, { crossOrigin: "Anonymous" });

#7


1  

You can't put spaces in your ID

你不能把空格放在你的ID里。

Update

更新

My guess is that image is on a different server than where you're executing the script. I was able to duplicate your error when running it on my own page, but it worked fine the moment I used an image hosted on the same domain. So it's security related - put the image on your site. Anyone know why this is the case?

我的猜测是,图像在不同的服务器上,而不是在执行脚本的地方。在我自己的页面上运行时,我能够复制您的错误,但在我使用同一个域上的映像时,它运行得很好。所以这是安全相关的-把图片放在你的网站上。有人知道为什么吗?

#8


1  

I was able to make it work using this:

我可以用这个来做这个:

Write this on first line of your .htaccess on your source server

在你的源服务器上的.htaccess的第一行写这个。

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

Then when creating an <img> element, do it as follows:

当创建一个为什么canvas.toDataURL()抛出一个安全异常?元素时,如下所示:

// 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');

#9


0  

If you are simply drawing some images on a canvas, make sure you are loading the images from the same domain.

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

www.example.com is different to example.com

www.example.com与example.com不同。

So make sure your images and the url you have in your address bar are the same, www or not.

所以要确保你的图像和你的地址栏里的url是相同的,www或者不是。

#10


0  

I'm using fabric.js and could resolve this by using toDatalessJSON instead of toDataURL:

我用织物。js可以使用toDatalessJSON而不是toDataURL解决这个问题:

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

Edit: Nevermind. This results in just the background image being exported to JPG, without the drawing on top so it was not entirely useful after all.

编辑:无所谓。这只会导致背景图像被导出到JPG,而不需要在顶部绘制,所以它毕竟不是完全有用的。

#1


67  

In the specs it says:

在说明书中,它说:

Whenever the toDataURL() method of a canvas element whose origin-clean flag is set to false is called, the method must raise a SECURITY_ERR exception.

只要调用了一个画布元素的toDataURL()方法,它的原clean标志被设置为false,那么该方法就必须抛出SECURITY_ERR异常。

If the image is coming from another server I don't think you can use toDataURL()

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

#2


17  

Setting cross origin attribute on the image objects worked for me (i was using fabricjs)

为我工作的图像对象设置跨源属性(我使用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';

For those using fabricjs, here's how to patch Image.fromUrl

对于那些使用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;
};

#3


16  

If the image is hosted on a host that sets either of Access-Control-Allow-Origin or Access-Control-Allow-Credentials, you can use Cross Origin Resource Sharing (CORS). See here (the crossorigin attribute) for more details.

如果该映像驻留在一个主机上,该主机设置了访问控制允许源或访问控制允许凭证,那么您可以使用跨源资源共享(CORS)。有关更多细节,请参见这里(crossorigin属性)。

Your other option is for your server to have an endpoint that fetches and serves an image. (eg. http://your_host/endpoint?url=URL) The downside of that approach being latency and theoretically unnecessary fetching.

您的另一个选项是您的服务器具有一个获取和服务图像的端点。(如。该方法的缺点是延迟和理论上不必要的抓取。

If there are more alternate solutions, I'd be interested in hearing about them.

如果有更多的替代解决方案,我很有兴趣听听他们的意见。

#4


13  

Seems there is a way to prevent that if image hosting able to provide the following HTTP headers for the image resources and browser supports CORS:

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

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

It is stated here: http://www.w3.org/TR/cors/#use-cases

这里有:http://www.w3.org/TR/cors/#用例。

#5


2  

I had the same problem and all the images are hosted in the same domain... So, if someone is having the same problem, here is how I solved:

我有同样的问题,所有的图片都在同一个域名中…所以,如果有人有同样的问题,我是这样解决的:

I had two buttons: one to generate the canvas and another one to generate the image from the canvas. It only worked for me, and sorry that I don't know why, when I wrote all the code on the first button. So when I click it generate the canvas and the image at the same time...

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

I always have this security problem when the codes were on different functions... =/

我总是有这样的安全问题当代码在不同的功能上…= /

#6


2  

Finally i found the solution. Just need add the crossOrigin as third param in fromURL func

最后我找到了解决方案。只需在fromURL func中添加第三个param。

fabric.Image.fromURL(imageUrl, function (image) {
            //your logic
    }, { crossOrigin: "Anonymous" });

#7


1  

You can't put spaces in your ID

你不能把空格放在你的ID里。

Update

更新

My guess is that image is on a different server than where you're executing the script. I was able to duplicate your error when running it on my own page, but it worked fine the moment I used an image hosted on the same domain. So it's security related - put the image on your site. Anyone know why this is the case?

我的猜测是,图像在不同的服务器上,而不是在执行脚本的地方。在我自己的页面上运行时,我能够复制您的错误,但在我使用同一个域上的映像时,它运行得很好。所以这是安全相关的-把图片放在你的网站上。有人知道为什么吗?

#8


1  

I was able to make it work using this:

我可以用这个来做这个:

Write this on first line of your .htaccess on your source server

在你的源服务器上的.htaccess的第一行写这个。

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

Then when creating an <img> element, do it as follows:

当创建一个为什么canvas.toDataURL()抛出一个安全异常?元素时,如下所示:

// 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');

#9


0  

If you are simply drawing some images on a canvas, make sure you are loading the images from the same domain.

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

www.example.com is different to example.com

www.example.com与example.com不同。

So make sure your images and the url you have in your address bar are the same, www or not.

所以要确保你的图像和你的地址栏里的url是相同的,www或者不是。

#10


0  

I'm using fabric.js and could resolve this by using toDatalessJSON instead of toDataURL:

我用织物。js可以使用toDatalessJSON而不是toDataURL解决这个问题:

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

Edit: Nevermind. This results in just the background image being exported to JPG, without the drawing on top so it was not entirely useful after all.

编辑:无所谓。这只会导致背景图像被导出到JPG,而不需要在顶部绘制,所以它毕竟不是完全有用的。