web-dev-qa-db-de.com

Leinwand, die durch Ursprungsdaten verfälscht ist

Ich lade eine Motion-JPEG-Datei von einer Drittanbieter-Site, auf die ich mich verlassen kann. Ich versuche getImageData(), aber der Browser (Chrome 23.0) beklagt Folgendes:

Unable to get image data from canvas because the canvas has been tainted by
cross-Origin data.

Es gibt einige ähnliche Fragen zu SO, aber sie verwenden lokale Dateien und ich verwende Medien von Drittanbietern. Mein Skript läuft auf einem gemeinsam genutzten Server und der Remote-Server ist nicht mein Eigentum.

Ich habe versucht img.crossOrigin = 'Anonymous' oder img.crossOrigin = '' (siehe diesen Beitrag auf dem Chromium-Blog über CORS ), aber es hat nicht geholfen. Irgendeine Idee, wie kann ich getImageData auf einer Leinwand mit Ursprungsdaten wechseln? Vielen Dank!

14
clwen

Sie können das crossOrigin-Flag nicht zurücksetzen, wenn es beschädigt ist. Wenn Sie jedoch vorher wissen, um welches Bild es sich handelt, können Sie es in eine Daten-URL konvertieren. Weitere Informationen finden Sie unter Zeichnen eines Bildes von einer Daten-URL in eine Leinwand .

Nein, Sie können und sollten nicht getImageData () von externen Quellen verwenden, die CORS nicht unterstützen

10
Paul Kaplan

Während die Frage sehr alt ist, bleibt das Problem bestehen und es gibt wenig im Internet, um es zu lösen. Ich habe eine Lösung gefunden, die ich teilen möchte:

Sie können das Bild (oder Video) verwenden, ohne dass das Attribut crossorigin zuerst gesetzt wurde, und testen, ob Sie über AJAX eine HEAD - Anforderung an dieselbe Ressource senden können. Wenn dies fehlschlägt, können Sie die Ressource nicht verwenden. Wenn dies gelingt, können Sie das Attribut hinzufügen und die Quelle des Bildes/Videos mit einem Zeitstempel versehen, der es neu lädt.

Diese Problemumgehung ermöglicht es Ihnen, dem Benutzer Ihre Ressource anzuzeigen und einige Funktionen einfach auszublenden, wenn CORS nicht unterstützt wird.

HTML:

<img id="testImage" src="path/to/image.png?_t=1234">

JavaScript:

var target = $("#testImage")[0];
    currentSrcUrl = target.src.split("_t=").join("_t=1"); // add a leading 1 to the ts
$.ajax({
    url: currentSrcUrl,
    type:'HEAD',
    withCredentials: true
})
.done(function() {
    // things worked out, we can add the CORS attribute and reset the source
    target.crossOrigin = "anonymous";
    target.src = currentSrcUrl;
    console.warn("Download enabled - CORS Headers present or not required");
    /* show make-image-out-of-canvas-functions here */
})
.fail(function() {
    console.warn("Download disabled - CORS Headers missing");
    /* ... or hide make-image-out-of-canvas-functions here */
});

Getestet und arbeitet mit IE10 + 11 und aktuellen Chrome 31, FF25, Safari 6 (Desktop) . Bei IE10 und FF kann es zu einem Problem kommen, wenn Sie versuchen, auf http-Dateien über ein https-Skript zuzugreifen. Ich weiß noch nicht, wie das Problem gelöst werden kann.

UPDATE Januar 2014:

Die dafür erforderlichen CORS-Header sollten wie folgt sein (Apache-Konfigurationssyntax):

Header set Access-Control-Allow-Origin "*"
Header set Access-Control-Allow-Headers "referer, range, accept-encoding, x-requested-with"

der X-Header ist nur für die Ajax-Anforderung erforderlich. Soweit ich das beurteilen kann, wird es nicht von allen, aber von den meisten Browsern verwendet

9
Jörn Berkefeld

Erwähnenswert ist auch, dass CORS angewendet wird, wenn Sie lokal arbeiten, unabhängig davon, ob sich die Ressource im selben Verzeichnis befindet wie die index.html-Datei, mit der Sie arbeiten. Für mich bedeutet dies, dass die CORS-Probleme verschwunden sind, als ich es auf meinen Server hochgeladen habe, da dieser eine Domäne hat.

5
Kristopher Ives

Sie können base64 des Bildes auf der Leinwand verwenden... Beim Konvertieren in base64 können Sie eine Proxy-URL ( https://cors-anywhere.herokuapp.com/ ) vor Ihrem Bildpfad verwenden, um Cross-Origin zu vermeiden Problem

Vollständige Details hier

https://stackoverflow.com/a/44199382/5172571

var getDataUri = function (targetUrl, callback) {
    var xhr = new XMLHttpRequest();
    xhr.onload = function () {
        var reader = new FileReader();
        reader.onloadend = function () {
            callback(reader.result);
        };
        reader.readAsDataURL(xhr.response);
    };
    var proxyUrl = 'https://cors-anywhere.herokuapp.com/';
    xhr.open('GET', proxyUrl + targetUrl);
    xhr.responseType = 'blob';
    xhr.send();
};
getDataUri(path, function (base64) {
    // base64 availlable here
})
1
Manish Mittal