web-dev-qa-db-fra.com

canvas.toDataURL () Security Error L'opération n'est pas sécurisée.

Lorsque j'essaie d'obtenir une capture d'écran et de l'enregistrer au format PNG avant de transférer une vidéo sur le serveur, le problème suivant se pose.

enter image description here

J'espère que vous pourrez résoudre mon problème ...

/*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

Cela ressemble à un problème de la SCRO.

La vidéo est sur une origine différente de celle du serveur Web.

Si vous pouvez obtenir que la vidéo inclue un en-tête "Access-Control-Allow-Origin: *" dans la réponse et que vous puissiez définir video.crossorigin = "Anonymous", vous pouvez probablement le retirer. 

J'ai utilisé le proxy Web Charles pour ajouter l'en-tête à toute image ou vidéo avec laquelle je voulais travailler.

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

Voir aussi https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes

Voici un Fiddle travaillant avec une image: 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/"

Est-ce ce que vous cherchez?

20
StephenKC

C'est à cause de Même origine politique . En gros, vous n'êtes pas autorisé à accéder aux données vidéo d'un élément chargé depuis un autre site/origine à l'aide d'un canevas.

Le dessin de données vidéo sur le canevas définit l'indicateur Origin-clean sur false, ce qui vous empêche d'obtenir les données d'image de quelque manière que ce soit.

Voir toDataURL pour plus d'informations.

11
tcooc

En outre, il a fallu quelques expériences pour arriver à cette conclusion, sur iOS, il semble que la position du paramètre .crossOrigin soit placée avant le. 

// 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

Dans docs toDataURL("data:image/png;") apparemment non documenté:

Essayez de remplacer .toDataURL("data:image/png;"); par .toDataURL("image/png");

1

Dans mon cas, le problème était lié à la présence d’icônes qui ne venaient pas de mon site ainsi qu’à la présence d’une entrée Select. Votre conteneur vidéo peut contenir les mêmes éléments. Pour résoudre ce problème, je devais masquer les entrées sélectionnées et les icônes avant la capture d'écran, puis les afficher à nouveau après la capture d'écran. Ensuite, le canvas.toDataURL fonctionnait parfaitement et ne lançait pas cette erreur de sécurité.

Avant capture d'écran:

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

Après la capture d'écran:

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

Salut, j'ai le même problème, dans un système où je montre des vidéos, mes utilisateurs doivent créer un pouce lorsqu'ils sélectionnent une vidéo, mais ensuite une erreur de sécurité.

Cette solution ne fonctionne que si vous pouvez modifier le serveur, vous pouvez alors envoyer la vidéo ou la police ou etc. avec CORS. Vous devez donc éditer httpd.conf (configuration Apache du serveur sur lequel vous extrayez les vidéos).

<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>

et dans votre page Web ou votre application, à la balise video, ajoutez: crossOrigin="Anonymous"

Ceci est un fragment de mon code, après que tout fonctionne à nouveau ..

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

Avec ceci, canvas.toDataURL() ne génère pas d'erreur