问题
I have a site running at pixie.strd6.com and images hosted through Amazon S3 with a CNAME for images.pixie.strd6.com.
I would like to be able to draw these images to an HTML5 canvas and call the getImageData method but it throws Error: SECURITY_ERR: DOM Exception 18
I have tried setting window.domain = \"pixie.strd6.com\"
, but that has no effect.
Additionally, $.get(\"http://dev.pixie.strd6.com/sprites/8516/thumb.png?1293830982\", function(data) {console.log(data)})
also throws an error: 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.
Ideally HTML5 canvas wouldn\'t block calling getImageData
from subdomains. I\'ve looked into setting an Access-Control-Allow-Origin header in S3, but haven\'t succeeded.
Any help or workarounds are greatly appreciated.
回答1:
Amazon recently announced CORS support
We're delighted to announce support for Cross-Origin Resource Sharing (CORS) in Amazon S3. You can now easily build web applications that use JavaScript and HTML5 to interact with resources in Amazon S3, enabling you to implement HTML5 drag and drop uploads to Amazon S3, show upload progress, or update content. Until now, you needed to run a custom proxy server between your web application and Amazon S3 to support these capabilities.
How to enable CORS
To configure your bucket to allow cross-origin requests, you create a CORS configuration, an XML document with rules that identify the origins that you will allow to access your bucket, the operations (HTTP methods) will support for each origin, and other operation-specific information. You can add up to 100 rules to the configuration. You add the XML document as the cors subresource to the bucket.
回答2:
One possible solution is to use nginx to act as a proxy. Here is how to configure urls going to http://pixie.strd6.com/s3/ to pass on through to S3, but the browser can still believe that it is non-cross domain.
location /s3/ {
proxy_pass http://images.pixie.strd6.com/;
}
回答3:
If you are using PHP, you can do something like:
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;
}
And access the image by using that php file, like if the file is called generateImage.php you can do <img src="http://GENERATEPHPLOCATION/generateImage.php"/>
and the external image url can be a get parameter for the file
回答4:
Recently, I came across $.getImageData, by Max Novakovic. The page includes a couple of neat demos of fetching and operating on Flickr photos, along with some code examples.
It allows you to fetch an image in JavaScript-manipulable form from an arbitrary site. It works by appending a script to the page. The script then requests the image from a Google App Engine server. The server fetches the requested image and relays it converted to base64 to the script. When the script receives the base64, it passes the data to a callback, which can then draw it onto a canvas and begin messing with it.
回答5:
In the past Amazon S3 didn't allow you to modify or add the access-control-allow-origin and access-control-allow-credentials HTTP headers so it may have been better to switch to a different service like Rackspace Cloud Files or some other service that does.
Add or modify the HTTP headers like this:
access-control-allow-origin: [your site]
access-control-allow-credentials: true
See http://www.w3.org/TR/cors/#use-cases for more information.
Using a service that allows you to modify the HTTP headers entirely solves the same origin problem.
回答6:
For people who do not use S3 can try to build a image proxy that encode the image file and wrap it into a JSON object.
Then you can use JSONP which supports cross domain to fetch the JSON object and assign the image data to img.src .
I wrote a sample code of the image proxy server with Google App Engine. https://github.com/flyakite/gae-image-proxy
The JSON object returns in the format like this
{
'height': 50,
'width' : 50,
'data' : 'data:image/jpeg;base64,QWRarjgk4546asd...QWAsdf'
}
The 'data' is the image data in base64 format. Assign it to a image.
img.src = result.data;
The image is now "clean" for your canvas.
回答7:
To edit your S3 bucket permissions:
1) Sign in to the AWS Management Console and open the Amazon S3 console at https://console.aws.amazon.com/s3/
2) In the Buckets list, open the bucket whose properties you want to view and click "add CORS configuration"

3) Write the rules you are willing to add in between the tags <CORSConfiguration>
<CORSConfiguration>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>*</AllowedHeader>
</CORSRule>
</CORSConfiguration>
You can learn more about rules at: http://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html
4) Specify crossorigin='anonymous' on the image you'll use in your canvas
回答8:
This behavior is by-design. Per the HTML5 spec, as soon as you draw a cross-origin image to a canvas, it is dirty and you can no longer read the pixels. Origin-matching compares the scheme, fully-qualified host, and in non-IE browsers, the port.
回答9:
Just bumped into the same problem. I found out about CORS that might be helpful.
http://html5-demos.appspot.com/static/html5-whats-new/template/index.html#14
It didn't work for me since I'm trying to manipulate an image from Flickr. So, I'm still looking for the solution.
来源:https://stackoverflow.com/questions/4672643/html5-canvas-getimagedata-and-same-origin-policy