web-dev-qa-db-ger.com

canvas.toDataURL () Sicherheitsfehler Der Vorgang ist nicht sicher

Wenn ich versuche, einen Screenshot zu erhalten und ihn als PNG-Datei zu speichern, bevor ich ein Video auf den Server hochlade, habe ich folgendes Problem

enter image description here

Ich hoffe du kannst mein Problem lösen ...

/*Output image show view*/
$('#file_browse').change(function(e){
    getVideo(this);
});

var capbtn = document.querySelector('#video_capture');
var video = document.querySelector('video');
var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');
var w, h, ratio;

video.addEventListener('loadedmetadata', function() {
    ratio = video.videoWidth / video.videoHeight;
    w = video.videoWidth - 100;
    h = parseInt(w / ratio, 10);
    canvas.width = w;
    canvas.height = h;           
}, false);

capbtn.addEventListener("click", function(){
    context.fillRect(0, 0, w, h);
    context.drawImage(video, 0, 0, w, h);
    var objImageData = canvas.toDataURL("data:image/png;");  
});

function getVideo(input) {
    if (input.files && input.files[0]) {
        var reader = new FileReader();
        reader.onload = function (e) {
            var video = document.getElementsByTagName('video')[0];
            var sources = video.getElementsByTagName('source');
            sources[0].src = e.target.result;
            video.load();
            video.style.display="block";
        }
        reader.readAsDataURL(input.files[0]);
    }
}
<input id="video_capture" type="submit" value="Capture" />
<video id="video_view" controls>
    <source src="movie.mp4" type="video/mp4">
</video>
<canvas width="300" height="300"></canvas>
19
Kemal

Klingt nach einem CORS-Problem.

Das Video hat einen anderen Ursprung als der Webserver.

Wenn Sie das Video mit einem Header "Access-Control-Allow-Origin: *" in die Antwort aufnehmen können und video.crossorigin = "Anonymous" einstellen können, können Sie dies wahrscheinlich abbrechen. 

Ich habe Charles Web Proxy verwendet, um den Header zu jedem Bild oder Video hinzuzufügen, mit dem ich arbeiten wollte.

Siehe https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image

Siehe auch https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes

Hier ist ein Fiddle, der mit einem Image arbeitet: http://jsfiddle.net/mcepc44p/2/

var canvas = document.getElementById("canvas").getContext("2d");

var button = document.getElementById("button");

var image = new Image();
image.crossOrigin = "anonymous";  // This enables CORS
image.onload = function (event) {
    try {
        canvas.drawImage(image, 0, 0, 200, 200);
        button.download = "cat.png";
        button.href = canvas.canvas.toDataURL();        
    } catch (e) {
        alert(e);
    }
};
image.src = "https://i.chzbgr.com/maxW500/1691290368/h07F7F378/"

Ist es das, wonach du suchst?

20
StephenKC

Es liegt an der Same Origin Policy . Grundsätzlich dürfen Sie nicht über eine Leinwand auf die Videodaten von etwas zugreifen, das von einem anderen Origin/Standort geladen wurde.

Wenn Sie Videodaten auf der Leinwand zeichnen, wird das Flag Origin-clean auf false gesetzt, sodass Sie die Bilddaten auf keine Weise abrufen können.

Siehe toDataURL für weitere Informationen.

11
tcooc

Um zu dieser Schlussfolgerung zu gelangen, brauchte man einige Experimente, um herauszufinden, dass die Position des .crossOrigin-Parameters vor iOS vor der .src stehen sollte 

// Webkit will throw security error when image used on canvas and canvas.toDataUrl()

return new Promise((resolve, reject) => {
  let image = new Image();
  img.onload = () => {resolve(image)}
  img.src = `${url}?${Date.now()}`;
  img.crossOrigin = ""
})

// Webkit will not throw security error when image used on canvas and canvas.toDataUrl()

return new Promise((resolve, reject) => {
  let img = new Image()
  img.onload = () => {resolve(img)}
  img.crossOrigin = ''
  img.src = `${url}?${Date.now()}`
})
1
Dotgreg

In Dokumenten toDataURL("data:image/png;") offenbar nicht dokumentiert:

Versuchen Sie, .toDataURL("data:image/png;"); durch .toDataURL("image/png"); zu ersetzen.

In meinem Fall war das Problem auf das Vorhandensein von Symbolen zurückzuführen, die nicht von meiner Website kamen, sowie das Vorhandensein eines Select-Eingangs. Ihr Videocontainer enthält möglicherweise dieselben Elemente. Um das Problem zu lösen, musste ich die ausgewählten Eingaben und Symbole ausblenden, bevor der Screenshot aufgenommen wurde, und sie dann nach der Aufnahme erneut anzeigen. Dann hat die canvas.toDataURL einwandfrei funktioniert und diesen Sicherheitsfehler nicht ausgelöst.

Vor dem Screenshot:

$("select[name='example']").add(".external-icon").hide();

Nach dem Screenshot:

$("select[name='example']").add(".external-icon").show();
0
codeymcgoo

Hallo, ich habe das gleiche Problem. In einem System, in dem ich Videos zeige, müssen meine Benutzer einen Daumen erstellen, wenn sie ein Video auswählen, aber dann Sicherheitsfehler.

Diese Lösung funktioniert nur, wenn Sie den Server ändern können. Dann können Sie das Video oder die Schriftart usw. mit CORS senden. Sie müssen also httpd.conf (Apache-Konfiguration vom Server, auf den Sie die Videos ziehen) bearbeiten.

<IfModule mod_setenvif.c>
    <IfModule mod_headers.c>
        <FilesMatch "\.(mp4)$">
            SetEnvIf Origin ":" IS_CORS
            Header set Access-Control-Allow-Origin "*" env=IS_CORS
        </FilesMatch>
    </IfModule>
</IfModule>

und in Ihrer Webseite oder App zum Video-Tag hinzufügen: crossOrigin="Anonymous"

Dies ist ein Fragment meines Codes, danach funktioniert alles wieder ..

document.getElementById('video_thumb').innerHTML =
             '<img src="'+data_uri+'"  width="250"
                        height="250px" crossOrigin="Anonymous">';       

Mit diesem Fehler trowst canvas.toDataURL() keinen Fehler