簡體   English   中英

JavaScript:toDataUrl()拋出“安全錯誤:可能無法導出受污染的畫布”。

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM