HTML5 Canvas getImageData和Same Origin Policy

时间:2011-01-12 18:44:02

标签: html5 canvas subdomain same-origin-policy

我有一个运行在pixie.strd6.com的网站,图片通过Amazon S3托管,图片为CNAME for images.pixie.strd6.com。

我希望能够将这些图像绘制到HTML5画布并调用getImageData方法,但它会抛出Error: SECURITY_ERR: DOM Exception 18

我已尝试设置window.domain = "pixie.strd6.com",但这没有效果。

此外,$.get("http://dev.pixie.strd6.com/sprites/8516/thumb.png?1293830982", function(data) {console.log(data)})也会引发错误:XMLHttpRequest cannot load http://dev.pixie.strd6.com/sprites/8516/thumb.png?1293830982. Origin http://pixie.strd6.com is not allowed by Access-Control-Allow-Origin.

理想情况下,HTML5画布不会阻止从子域调用getImageData。我已经研究过在S3中设置Access-Control-Allow-Origin标头,但还没有成功。

非常感谢任何帮助或解决方法。

9 个答案:

答案 0 :(得分:6)

Amazon recently announced CORS support

  

我们很高兴地宣布支持Amazon S3中的跨源资源共享(CORS)。您现在可以轻松构建使用JavaScript和HTML5与Amazon S3中的资源交互的Web应用程序,使您能够实现HTML5拖放上传到Amazon S3,显示上载进度或更新内容。到目前为止,您需要在Web应用程序和Amazon S3之间运行自定义代理服务器以支持这些功能。

How to enable CORS

  

要配置存储桶以允许跨源请求,您需要创建一个CORS配置,一个XML文档,其中包含用于标识允许访问存储桶的来源的规则,操作(HTTP方法)将支持每个源,和其他特定于操作的信息。您最多可以为配置添加100条规则。您将XML文档作为cors子资源添加到存储桶中。

答案 1 :(得分:4)

一种可能的解决方案是使用nginx作为代理。以下是如何配置转到http://pixie.strd6.com/s3/的网址以传递到S3,但浏览器仍然可以认为它是非跨网域。

location /s3/ {
  proxy_pass http://images.pixie.strd6.com/;
}

答案 2 :(得分:3)

如果您使用的是PHP,则可以执行以下操作:

    function fileExists($path){
        return (@fopen($path,"r")==true);
    }
    $ext = explode('.','https://cgdev-originals.s3.amazonaws.com/fp9emn.jpg');
    if(fileExists('https://cgdev-originals.s3.amazonaws.com/fp9emn.jpg')){
        $contents = file_get_contents('https://cgdev-originals.s3.amazonaws.com/fp9emn.jpg');
        header('Content-type: image/'.end($ext));
        echo $contents;
    }

使用该php文件访问图像,就像文件名为generateImage.php一样,你可以<img src="http://GENERATEPHPLOCATION/generateImage.php"/>,外部图片网址可以是文件的get参数

答案 3 :(得分:2)

最近,我遇到了马克·诺瓦科维奇的$.getImageData。该页面包含一些在Flickr照片上获取和操作的简洁演示,以及一些代码示例。

它允许您从任意站点以JavaScript可操作的形式获取图像。它的工作原理是在页面上附加一个脚本。然后,该脚本从Google App Engine服务器请求图像。服务器获取请求的图像并将其转换为base64的中继转发给脚本。当脚本收到base64时,它会将数据传递给回调,然后回调可以将其绘制到画布上并开始搞乱它。

答案 4 :(得分:2)

过去,Amazon S3不允许您修改或添加access-control-allow-origin和access-control-allow-credentials HTTP标头,因此最好切换到Rackspace Cloud等其他服务文件或其他一些服务。

添加或修改HTTP标头,如下所示:

access-control-allow-origin: [your site]
access-control-allow-credentials: true

有关详细信息,请参阅http://www.w3.org/TR/cors/#use-cases

使用允许您修改HTTP标头的服务完全解决了相同的原始问题。

答案 5 :(得分:2)

对于不使用S3的人,可以尝试构建一个对图像文件进行编码并将其包装到JSON对象中的图像代理。

然后你可以使用支持跨域的JSONP来获取JSON对象并将图像数据分配给img.src。

我使用Google App Engine编写了图像代理服务器的示例代码。 https://github.com/flyakite/gae-image-proxy

JSON对象以这样的格式返回

{ 
  'height': 50, 
  'width' : 50, 
  'data'  : 'data:image/jpeg;base64,QWRarjgk4546asd...QWAsdf'
} 

'data'是base64格式的图像数据。将其分配给图像。

img.src = result.data;

图片现在为您的画布“干净”。

答案 6 :(得分:2)

编辑S3存储桶权限:

1)登录AWS管理控制台并在https://console.aws.amazon.com/s3/

打开Amazon S3控制台

2)在Buckets列表中,打开要查看其属性的存储桶,然后单击“添加CORS配置”

amazon-screen-shot

3)在标签<CORSConfiguration>

之间写下您愿意添加的规则
<CORSConfiguration>
  <CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
  </CORSRule>
</CORSConfiguration>

您可以在http://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html

了解有关规则的更多信息

4)在您将在画布中使用的图像上指定crossorigin ='anonymous'

答案 7 :(得分:1)

此行为是按设计进行的。根据HTML5规范,只要将交叉原始图像绘制到画布上,它就会变脏并且您无法再读取像素。 Origin-matching比较方案,完全限定主机,在非IE浏览器中比较端口。

答案 8 :(得分:1)

刚刚碰到同样的问题。我发现了可能有用的CORS。

http://html5-demos.appspot.com/static/html5-whats-new/template/index.html#14

因为我试图操纵Flickr中的图像,所以它对我不起作用。所以,我仍然在寻找解决方案。