canvas图像跨平台不安全的错误
我有这个代码来创build从不同的服务器URL的canvas图像
function getBase64Image(imageUri) { var canvas = document.createElement("canvas"); ctx = canvas.getContext("2d"); var img = new Image(); img.src = imageUri; img.crossOrigin = "Anonymous"; img.onload = function() { canvas.width = this.width; canvas.height = this.height; ctx.drawImage(img, 0, 0, this.width, this.height); var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); var dataURL = canvas.toDataURL("image/png"); document.getElementById("dummyhiddenField").value = dataURL; }; }
我试图从服务器获取图像,并将其设置为隐藏字段的canvasurl,但只能使用本地图像
根据从stackoverflow的其他答案我设置crossOrigin = "Anonymous"
这是不工作也无法设置访问来源从服务器,必须pipe理localscript所有的东西
谢谢
带有跨域内容的Html5 Canvas更新后的外观
以下是关于跨域内容如何影响html5canvas以及如何在适用于跨域内容的安全性限制内工作的更新
更新今天(2016年1月)非常有用,因为有几个新的(ish)方法允许跨域图像绘制到canvas而不会污损canvas。
在HTML5canvas上绘制跨网域内容会导致它“被污染”
您可以从canvas上的另一个域中绘制图像,并将显示在canvas上。 从另一个域访问资源被称为“跨源资源共享” – 通常简称为“CORS”。
绘制CORS内容(f.ex:images)会导致canvas被“污染”,出于安全原因。
如果canvas被污染,则不能使用这些canvas和上下文方法:
-
context.getImageData
获取canvas上的像素数据 -
canvas.toDataURL
将canvas导出为图像
你不能“欺骗”canvas违反其CORS安全限制 – 希望你甚至不想尝试! 但是,通过满足CORS安全限制,您可以绘制交叉图像,而不会污染canvas。
处理图像的“通常”(最简单的)方式,以免污染canvas:
将您的图片放在与网页相同的网域中。 您可以有几个物理服务器提供内容,但图像域必须与创buildcanvas的html代码(或JavaScript代码)相同。 CORS的限制是满意的,canvas没有污染。
在您自己的计算机上开发时关于CORS的注意事项
解决scheme#1(!):您可以在开发计算机上安装Web服务器,并从一个域提供网页文件(.html,.js等)和图像文件(.png,.jpg等)。
开发计算机的文件夹被声明为不同的域。 因此,从本地磁盘上的子目录中绘制图像将违反CORS限制,因为不同的本地文件夹是不同的域。
解决scheme2:在开发过程中,您可以将网页文件和图像文件放在桌面上,图像将被声明在同一个域中,并且您的canvas不会被污染。
当图像位于不同的域时,满足CORS限制
解决scheme3:您可以在canvas上使用跨域图像而不会污染它。 为此,您必须满足以下要求:
-
Clientside:图像对象必须将
crossOrigin
属性设置为允许跨源内容。 这个属性可以在html元素标签内或在javascript内设置。 启用设置是“匿名”和“使用凭据”。 -
服务器端:服务器必须configuration为返回标题,表明响应包含授权内容。
取决于configuration,可能需要多个响应标题:
Access-Control-Allow-Origin
将返回匿名授权( *
),或将返回基于请求的特定授权。
如果authentication需要附加信息(如Cookie),则需要Access-Control-Allow-Credentials
。
Access-Control-Expose-Headers
使客户端可以访问额外的响应信息。
在服务器上启用跨域请求可能很复杂,特别是在提供基于客户端angular色授权的内容时。 有关启动configuration的更多信息,请访问: http : //enable-cors.org/index.html 。
使用允许匿名访问其图像的跨域图像主机
解决scheme#4:某些公共图像主机允许您以CORS兼容的方式上传将提供给客户端的图像。 几个例子是: imgur和dropbox 。 Stackoverflow图像托pipe在Imgur上。
以下是以符合CORS标准的方式在Dropbox.com上投放图片的示例:
- 注册一个Dropbox帐户 。
- 你有几个默认的文件夹。 上传您的图像在特殊的“公共”文件夹。 这是Dropbox提供符合CORS的匿名访问的文件夹。
- 右键点击您要提供的图片,然后select“复制公共链接”。 您的剪贴板将有一个链接到您的CORS兼容图像。
- 用img标签或javascript将图片加载到您的页面上。
以下是使用javascript从Dropbox获取CORS兼容图像对象的示例代码:
var img=new Image(); img.crossOrigin='anonymous'; img.src="https://dl.dropboxusercontent.com/u/139992952/multple/sun.png"; img.onload=start; function start(){ context.drawImage(img,0,0); // The canvas is not tainted so // the following both work without errors var url=canvas.toDataURL(); var imageData=context.getImageData(0,0,100,100); }
新(ish):通过让客户端用户同意CORSS
CORS安全限制是为了阻止坏人偷偷带你的信息,而让你不知道。
直到最近,浏览器都依赖于客户端 – 服务器configuration来满足安全需求。 最近,如果用户肯定参与决定使用什么内容,浏览器已经开始允许跨源内容。
解决scheme5: Chrome和Firefox现在允许客户端用户right click the canvas & save the canvas as an image
。 这是使用canvas.toDataURL
创build一个图像对象并将该图像对象保存到本地驱动器的手册。 CORS是满意的,因为用户决定canvas内容是否适合保存到他们的本地驱动器,他们肯定地右键单击以启动下载过程。
解决scheme#6:您可以使用input element, type='file'
让客户端用户select一个图像。 用户甚至可以select一个互联网URL( http:// .. )。 再次,CORS是满意的,因为用户参与select过程。
以下是显示如何侦听用户使用inputselect图像的示例代码:
// canvas vars var canvas=document.createElement("canvas"); var ctx=canvas.getContext("2d"); // define max resulting image width,height (after resizing) var maxW=100; var maxH=100; // listen for user to select files var input = document.getElementById('input'); input.addEventListener('change', handleFiles); function handleFiles(e) { var img = new Image; img.onload = function(){ var iw=img.width; var ih=img.height; // scale down, if necessary if(iw>maxW || ih>maxH){ var scale=Math.min((maxW/iw),(maxH/ih)); iw*=scale; ih*=scale } // set canvas width/height to scaled size canvas.width=iw; canvas.height=ih; // draw+scale the img onto the canvas ctx.drawImage(img,0,0,iw,ih); // create a jpeg URL (with medium quality to save "weight") var jpg=canvas.toDataURL('image/jpeg',0.60); // In Demo: add the jpg to the window // In production, accumulate jpg's & send to server $('<img />',{src:jpg}).appendTo('body'); } // In Demo: Just process the first selected file // In production: process all selected files img.src = URL.createObjectURL(e.target.files[0]); }
body{ background-color: ivory; } #canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> <h4>You can even enter a web URI (http://...)</h4> <input type="file" id="input"/><br>