2011-08-20 242 views
25

问题:哪些浏览器版本支持跨域的CORS(跨源资源共享)标头图片在Canvas中使用?浏览器Canvas CORS支持跨域加载的图像处理

CORS可以应用于跨域XMLHttpRequests和图像请求。这个问题是关于图像请求我正常去浏览器版本兼容http://caniuse.com/cors目前尚不清楚的问题和谷歌搜索没有产生好的结果。

我确实发现了一个最近的chrome开发博客,暗示CORS支持在现代浏览器中广泛传播,但可能因WebGL安全问题而中断。
http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html

上CORS的更多细节:

我们正在考虑使用帆布& CORS与作为W3C工作草案http://www.w3.org/TR/cors/#use-cases描述跨域图像请求的可行性。 CORS被html canvas使用,以类似于flash使用crossdomain.xml的方式允许跨域资源使用。基本上,我们想要读取/编辑图像数据像素,我们不想使用同一个原始代理服务器。

通常情况下,如果图像加载跨域并与html canvas一起使用,则使用像canvas.toDataURL()这样的函数访问像素将引发安全错误。但是,如果传递图像的服务器添加这样的标题,则应允许跨域使用。

access-control-allow-origin: * 

浏览器,我们最关心的:

我们计划来解决IE的缺乏画布支持使用闪光灯,所以与CORS问题的桌面浏览器,我们可以做到这一点为好,但移动闪存不是一个选项,并且使用代理来使请求相同的来源不是我们用例中的选项。所以,我对Andriod,Iphone,CORS的IPAD浏览器支持特别感兴趣。

回答

19

测试结果:坏消息,它似乎只适用于Chrome。 所有其他浏览器(包括Android手机)给出了如下的错误:

Failed: DOM Exception: SECURITY_ERR (18) 

移动设备我测试的Android(三星Galaxy内核版本2.6.32.9),iPhone和iPad的V1,它在所有三个失败。

你可以用这个URL测试自己的移动设备: http://maplarge.com/CrossOriginImageTest.html

测试脚本:

<!DOCTYPE html> 
<html> 
<head> 
<title>Canvas Cross Origin Image Test: Testing for Canvas Cross Domain Image CORS Support</title> 
<script type="text/javascript"> 
    function initialize() { 

     //will fail here if no canvas support 
     try { 
      var can = document.getElementById('mycanvas'); 
      var ctx = can.getContext('2d'); 
      var img = new Image(); 
      img.crossOrigin = ''; 
      //domain needs to be different from html page domain to test cross origin security 
      img.src = 'http://lobbydata.com/Content/images/bg_price2.gif'; 
     } catch (ex) { 
      document.getElementById("results").innerHTML = "<span style='color:Red;'>Failed: " + ex.Message + "</span>"; 
     } 

     //will fail here if security error 
     img.onload = function() { 
      try { 
       var start = new Date().getTime(); 
       can.width = img.width; 
       can.height = img.height; 
       ctx.drawImage(img, 0, 0, img.width, img.height); 
       var url = can.toDataURL(); // if read succeeds, canvas isn't dirty. 
       //get pixels 
       var imgd = ctx.getImageData(0, 0, img.width, img.width); 
       var pix = imgd.data; 
       var len = pix.length; 
       var argb = []; //pixels as int 
       for (var i = 0; i < len; i += 4) { 
        argb.push((pix[i + 3] << 24) + (pix[i] << 16) + (pix[i + 1] << 8) + pix[i + 2]); 
       } 
       var end = new Date().getTime(); 
       var time = end - start; 
       document.getElementById("results").innerHTML = "<span style='color:Green;'>" + 
       "Success: Your browser supports CORS for cross domain images in Canvas <br>"+ 
       "Read " + argb.length+ " pixels in "+ time+"ms</span>"; 
      } catch (ex) { 
       document.getElementById("results").innerHTML = "<span style='color:Red;'>Failed: " + ex + "</span>"; 
      } 

     } 

    } 
</script> 
</head> 
<body onload="initialize()"> 
<h2>Canvas Cross Origin Image Test: Testing for Canvas Cross Domain Image CORS Support</h2> 
<h2><a href="http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html">What is CORS Image Security?</a></h2> 
<h1 id="results" style="color:Orange;">Testing...</h1> 
<canvas id="mycanvas"></canvas> 
<br /> 
<a href="/Example/List">More Examples</a> 
</body> 
</html> 
+2

我正要张贴这个问题。很高兴我不是唯一一个疯狂的人认为这个*应该*工作。这现在在FF17中工作,但仍然不能在IE10中工作。猜猜我必须继续使用我的请求代理。 – pseudosavant

+2

1.5年后更新:在Windows上,我只测试了IE9(失败),Safari 5.0.5(失败),Firefox(通行证)和Chrome(通行证) – Glenn

+0

在safari上检查了iPad 3上的演示页面,并且工作正常。 – metric152

3

我只是测试这在Safari和Chrome浏览器我的iPhone运行iOS 6并且您的测试页通过测试。我会发布此评论作为评论,但我没有给你的答案发表评论的选项。

+0

好消息!我的帖子是一年半的时间,所以我很高兴看到浏览器进步。 – Glenn

+1

我在Windows 8 - IE 10中测试过,但仍然失败。 – bfcoder

+1

在Mac OSX 10.7.5 - Safari 6.0.2中测试通过。 – bfcoder

1

你可以使用PHP来获得下面的所有你想要的东西,而不CROS,工作示例:

<script src="http://code.jquery.com/jquery-latest.js"></script> 
<script> 
function a(x){ 
alert(x); 
var img = new Image(); 
      img.onload = function() 
      { 
      var canvas = document.createElement("canvas"); 
      canvas.width = img.width; 
      canvas.height = img.height; 
      var context = canvas.getContext("2d"); 
      context.fillStyle = "#ffffff"; 
      context.fillRect(0,0,img.width,img.height); 
      context.drawImage(img, 0, 0); 
      var data = canvas.toDataURL('image/jpeg' , 0.8); 
      document.write('<img src="'+data+'" />'); 
      };img.src = x; 
} 
</script> 
<?php 
$im = imagecreatefromjpeg('http://www.nasa.gov/images/content/711375main_grail20121205_4x3_946-710.jpg'); 
      ob_start(); 
      imagejpeg($im,NULL,100); 
      $outputBuffer = ob_get_clean(); 
      $base64 = base64_encode($outputBuffer); 
      $x= 'data:image/jpeg;base64,'.$base64; 
      echo "<script>a('".$x."')</script>"; 
?> 
+2

这看起来像一个代理服务。如果您控制托管该页面的域并且可以添加此脚本,它应该可以工作。但是,如果你不这样做,你就会被困在处理CORS的限制中。对于托管可嵌入窗口小部件或提供api服务的网站而言,这尤其痛苦,因为这意味着每个想要使用画布触摸图像的用户都必须设置自己的域特定代理,如果他们想要适应不正确的浏览器实施CORS。由于这个问题在很多浏览器中都很常见,所以不能忽略。 – Glenn

+1

最重要的是获得base64解码图像到画布,因为没有CORS限制。而在API服务中,也有可能向客户端提供base64解码图像而不是图像URL。 – varoniic

+0

如果你的32KB以下,你甚至可以得到IE8的支持。我很好奇文本转换膨胀和解码​​性能。你有没有运行任何统计数据?这家伙建议臃肿可能相当大http://appcropolis.com/javascript-encode-images-dataurl/ – Glenn