![](/img/trans.png)
[英]Why am I getting the error “Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported. ”
[英]JavaScript: toDataUrl() throwing “Security Error: Tainted canvases may not be exported.”
我有一个HTML5画布,我从svg中绘制一个图像。
HTML
<canvas id="canvas" width="600" height="320"></canvas>
JavaScript的
var DOMURL = window.URL || window.webkitURL || window;
var data = '<svg xmlns="http://www.w3.org/2000/svg" width="600" height="320">'+
'<foreignObject width="100%" height="100%">'+
'<style>'+
'foreignObject {'+
'background-color: #000;'+
'color: #fff'+
'border-radius: 10px;'+
'}'+
'h1 {'+
'color: #2acabd;'+
'font: 25px arial;'+
'font-weight: bold;'+
'text-align: center;'+
'}'+
'h2 {'+
'margin: 0;'+
'color: #2acabd;'+
'font: 15px arial;'+
'}'+
'p {'+
'color: #fff;'+
'}'+
'</style>'+
'<div xmlns="http://www.w3.org/1999/xhtml" style="font-size: 40px;">'+
'<h1>Heading</h1>'+
'<div>'+
'<div id="details-wrapper">'+
'<h2>Full Name</h2>'+
'<p>Alan Johnson</p>'+
'<h2>Date of Birth</h2>'+
'<p>7th November 1988</p>'+
'<p><span id="user-id">34329483028493284093284432</span></p>'+
'</div>'+
'</div>'+
'</div>'+
'</foreignObject>'+
'</svg>';
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
img = new Image();
img.setAttribute("crossOrigin", "anonymous");
var svg = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
var url = DOMURL.createObjectURL(svg);
img.onload = function() {
ctx.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
console.log(canvas.toDataURL());
}
img.src = url;
(JS小提琴: https : //jsfiddle.net/LondonAppDev/qnpcg8th/1/ )
当我调用canvas.toDataURL()
,我得到了异常:
(index):98 Uncaught SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
我已经在Stack Overflow上看到了与此异常相关的许多其他问题和答案。 我的问题是不同的,因为(正如你所看到的)我不是在任何一点,包括我的svg或画布中来自另一个域的任何图像。
我猜测问题是我正在使用DOMURL.createObjectURL
创建一个对象URL。
我知道在不同的浏览器中执行此操作存在一些兼容性问题,但此应用只需要在Chrome中运行。 此外,直接将文本绘制到画布上是不可取的,我必须通过svg来完成。
关于如何解决这个问题,并成功获得我的画布的PNG的任何想法?
我通过将svg转换为数据URL而不是Blob来解决这个问题。
我删除了var url = DOMURL.createObjectURL(svg);
并替换了img.src = url;
有了这个:
function buildSvgImageUrl(svg) {
b64 = window.btoa(svg);
return "data:image/svg+xml;base64," + b64;
}
img.src = buildSvgImageUrl(data);
现在它完美无缺。
这 是出于安全和用户隐私的原因。
在画布上绘制<foreignObject>
可能会泄漏有关用户的几个信息,在此之前,chrome团队认为他们没有足够的安全措施来防止这种情况,因此他们确实污染了画布。
以下是有关此问题的铬虫报告 。
但是当OP发现时,他们有一个实现错误,忘记在dataURI版本上设置这个限制。
我发布了这个错误报告 ,说明他们没有使用dataURI污染画布。
所有这些都导致了前一个限制的影响,因此在下一版本的chrome中,我们应该能够在画布上绘制<foreignObject>
而不会污染它,即使使用BlobURI也是如此。
但请注意,Safari仍然具有相同的限制(没有实现错误,即dataURI hack在那里不起作用),并且IE <Edge不支持<foreignObject>
元素并且当任何 SVG被绘制到时会污染画布它确实删除了所有UserAgent和OS样式(导致与您期望的结果不同的结果)。
一个真正的解决方法是不使用这个hack来绘制你的元素,而是使用CanvasAPI绘图方法绘制所有HTML(就像html2canvas那样)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.