canvas.toDataURL () SecurityError

76

Ich verwende also Google Maps und bekomme das Bild so, dass es so aussieht

<img id="staticMap"
        src="http://maps.googleapis.com/maps/api/staticmap?center=Brooklyn+Bridge,New+York,NY&zoom=13&size=600x300&maptype=roadmap
&markers=color:blue%7Clabel:S%7C40.702147,-74.015794&markers=color:green%7Clabel:G%7C40.711614,-74.012318
&markers=color:red%7Ccolor:red%7Clabel:C%7C40.718217,-73.998284&sensor=false">

Ich muss es retten. Ich habe folgendes gefunden:

function getBase64FromImageUrl(URL) {
    var img = new Image();
    img.src = URL;
    img.onload = function() {

        var canvas = document.createElement("canvas");
        canvas.width = this.width;
        canvas.height = this.height;

        var ctx = canvas.getContext("2d");
        ctx.drawImage(this, 0, 0);

        var dataURL = canvas.toDataURL("image/png");

        alert(dataURL.replace(/^data:image\/(png|jpg);base64,/, ""));

    };
}

Aber ich bekomme dieses Problem:

Nicht erfasster Sicherheitsfehler: Fehler beim Ausführen von 'toDataURL' auf 'HTMLCanvasElement': Beschmutzte Leinwände können möglicherweise nicht exportiert werden.

Ich habe nach Korrekturen gesucht. Ich habe hier ein Beispiel gefunden, wie man CORS verwendet, aber ich kann diese beiden Codeteile immer noch nicht zusammenbinden, damit es funktioniert. Vielleicht mache ich es falsch und es gibt einen einfacheren Weg, es zu tun? Ich versuche, dieses Bild zu speichern, damit ich die Daten auf meinen Server übertragen kann. Vielleicht hat jemand so etwas gemacht und weiß, wie man .toDataURL()Arbeit macht, wenn ich sie brauche?

user3074343
quelle

Antworten:

99

Wenn Google dieses Bild nicht mit der richtigen Access-Control-Allow-OriginKopfzeile bereitstellt, können Sie das Bild nicht auf Leinwand verwenden. Dies liegt daran, dass keine CORSGenehmigung vorliegt. Sie können mehr über das lesen hier , aber es bedeutet im Wesentlichen:

Obwohl Sie Bilder ohne CORS-Genehmigung in Ihrer Leinwand verwenden können, verschmutzt dies die Leinwand. Sobald eine Zeichenfläche beschädigt wurde, können Sie keine Daten mehr aus der Zeichenfläche zurückziehen. Beispielsweise können Sie die Canvas-Methoden toBlob (), toDataURL () oder getImageData () nicht mehr verwenden. Andernfalls wird ein Sicherheitsfehler ausgegeben.

Dies schützt Benutzer vor der Offenlegung privater Daten, indem Bilder verwendet werden, um Informationen von Remote-Websites ohne Erlaubnis abzurufen.

Ich schlage vor, nur die URL an Ihre serverseitige Sprache zu übergeben und das Bild mit curl herunterzuladen. Achten Sie jedoch darauf, dies zu bereinigen!

BEARBEITEN:

Da diese Antwort immer noch die akzeptierte Antwort ist, sollten Sie die Antwort von @ shadyshrif lesen , die verwendet werden soll:

var img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.src = url;

Dies funktioniert nur , wenn Sie über die richtigen Berechtigungen verfügen, ermöglicht Ihnen jedoch zumindest, das zu tun, was Sie möchten.

Häftling
quelle
1
Ich würde den Remote-Alternativvorschlag von @Prisoner weiter verfolgen und vorschlagen, ihn zum Standardverhalten zu machen. Der Server kann mit ziemlicher Sicherheit die Datei img.src empfangen und dann * / * cURL das Bild schneller abrufen, als der Client ein Bild mit lokalem Ursprung codieren und an den Server senden könnte. Nur wenn eine clientseitige Authentifizierung erforderlich ist (dh der Versuch Ihres Servers endet mit a 403), können Sie möglicherweise auf die Verwendung zurückgreifen, canvas.toDataURL(img)in der Hoffnung, dass sie vom selben Ursprung wie die Seite bereitgestellt wird . Dieses Standardverhalten führt auch zur Originaldatei (EXIF et al.)
Alastair
4
Ich habe meinen Google Cloud Storage-Bucket auf "Access-Control-Allow-Origin: *" gesetzt, erhalte jedoch weiterhin diesen Sicherheitsfehler, wenn ich versuche, die toDataURL () -Methode zu verwenden. Das Bild wird dem Canvas über die URL zugestellt, die von "getImageServingUrl"
Mr Pablo
1
Noch eine Lösung? Diese Antwort bläst.
Yeats
Toll ! Vielen Dank für diese Antwort!
Kevin Vincent
4
TIL: Es ist wichtig, das crossOriginAttribut vor dem Festlegen festzulegen img.src.
Horstwilhelm
56

Verwenden Sie einfach das crossOriginAttribut und übergeben Sie es 'anonymous'als zweiten Parameter

var img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.src = url;
Schattiger Mohamed Sherif
quelle
6
Zur Verdeutlichung funktioniert dies nicht für Server, die die Ressource nicht direkt an Sie weitergeben. Dies bedeutet, dass dies nur für öffentliche Ressourcen oder falsch konfigurierte Server funktioniert.
m3nda
3
Ich musste der Bild-URL auch einen Zeitstempel hinzufügen, um zu verhindern, dass der Speicherserver ohne den Header Access-Control-Allow-Origin mit 304 antwortet. Soimg.src = url + '?' + new Date().getTime();
Kirby
funktionierte nicht für mich in IE11 mit Bildern die Daten-URL-Quelle verwenden
AlexM
4

Diese Methode verhindert, dass Sie von dem Server, auf den Sie zugreifen, den Fehler "Zugriffskontrolle-Zulassen-Ursprung" erhalten.

var img = new Image();
var timestamp = new Date().getTime();
img.setAttribute('crossOrigin', 'anonymous');
img.src = url + '?' + timestamp;
Karuban
quelle
3

Versuchen Sie den Code unten ...

<img crossOrigin="anonymous"
     id="imgpicture" 
     fall-back="images/penang realty,Apartment,house,condominium,terrace house,semi d,detached,
                bungalow,high end luxury properties,landed properties,gated guarded house.png" 
     ng-src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" 
     height="220"
     width="200"
     class="watermark">
ct.tan
quelle
2
Was ist der Grund für den sinnlosen Wert des fall-backAttributs?
y.bregey
0

In meinem Fall habe ich das WebBrowser-Steuerelement verwendet (IE 11 erzwingen) und konnte den Fehler nicht überwinden. Der Wechsel zu CefSharp, das Chrome verwendet, hat es für mich gelöst.

Brad Mathews
quelle
0

Ich hatte die gleiche Fehlermeldung. Ich hatte die Datei in einer einfachen .html, als ich die Datei an PHP in Apache übergab, funktionierte es

html2canvas(document.querySelector('#toPrint')).then(canvas => {
            let pdf = new jsPDF('p', 'mm', 'a4');
            pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 0, 0, 211, 298);
            pdf.save(filename);
        });
Rodolfo Gutierrez Nava
quelle
-3

Durch die Verwendung von Fabric js können wir dieses Sicherheitsfehlerproblem im IE lösen.

    function getBase64FromImageUrl(URL) {
        var canvas  = new fabric.Canvas('c');
        var img = new Image();
        img.onload = function() {
            var canvas1 = document.createElement("canvas");
            canvas1.width = this.width;
            canvas1.height = this.height;
            var ctx = canvas.getContext('2d');
            ctx.drawImage(this, 0, 0);
            var dataURL = canvas.toDataURL({format: "png"});
        };
        img.src = URL;
    }
Ganesan Js
quelle