web-dev-qa-db-fra.com

Pourquoi canvas.toDataURL () lève-t-il une exception de sécurité?

Est-ce que je n'ai pas assez dormi ou quoi? Ce code suivant

var frame=document.getElementById("viewer");
frame.width=100;
frame.height=100;

var ctx=frame.getContext("2d");
var img=new Image();
img.src="http://www.ansearch.com/images/interface/item/small/image.png"

img.onload=function() {
    // draw image
    ctx.drawImage(img, 0, 0)

    // Here's where the error happens:
    window.open(frame.toDataURL("image/png"));
}

jette cette erreur: 

SECURITY_ERR: DOM Exception 18

Il n'y a aucun moyen que cela ne fonctionne pas! Quelqu'un peut-il expliquer cela, s'il vous plaît?

87
pop850

Dans le specs il est écrit:

Chaque fois que la méthode toDataURL () d'un élément de toile dont le drapeau Origin-clean est défini sur false est appelée, la méthode doit déclencher une exception SECURITY_ERR.

Si l'image provient d'un autre serveur, je ne pense pas que vous puissiez utiliser toDataURL ()

67
Bob

La définition de l'attribut cross origin sur les objets de l'image a fonctionné pour moi (j'utilisais fabricjs)

    var c = document.createElement("img");
    c.onload=function(){
        // add the image to canvas or whatnot
        c=c.onload=null
    };
    c.setAttribute('crossOrigin','anonymous');
    c.src='http://google.com/cat.png';

Pour ceux qui utilisent fabricjs, voici comment patcher Image.fromUrl

// patch fabric for cross domain image jazz
fabric.Image.fromURL=function(d,f,e){
    var c=fabric.document.createElement("img");
    c.onload=function(){
        if(f){f(new fabric.Image(c,e))}
        c=c.onload=null
    };
    c.setAttribute('crossOrigin','anonymous');
    c.src=d;
};
17
Philip Nuzhnyy

Si l'image est hébergée sur un hôte définissant soit Access-Control-Allow-Origin, soit Access-Control-Allow-Credentials, vous pouvez utiliser le partage de ressources d'origine croisée (CORS). Voir ici (l'attribut crossorigin) pour plus de détails.

Votre autre option consiste pour votre serveur à avoir un point de terminaison qui récupère et sert une image. (par exemple. http: // your_host/endpoint? url = URL ) L’inconvénient de cette approche est le temps de latence et la récupération inutile en théorie.

S'il y a plus de solutions de rechange, j'aimerais en entendre parler.

16
James Foster

Il semble qu'il existe un moyen d'empêcher que si l'hébergement d'images puisse fournir les en-têtes HTTP suivants pour les ressources images et que le navigateur prenne en charge CORS:

access-control-allow-Origin: * 
 access-control-allow-credentials: true

Il est indiqué ici: http://www.w3.org/TR/cors/#use-cases

13
DitherSky

Finalement j'ai trouvé la solution. Il suffit d’ajouter la variable crossOrigin en tant que troisième paramètre dans fromURLfonc

fabric.Image.fromURL(imageUrl, function (image) {
            //your logic
    }, { crossOrigin: "Anonymous" });
2
jose920405

J'ai pu le faire fonctionner en utilisant ceci:

Écrivez ceci sur la première ligne de votre .htaccess sur votre serveur source

Header add Access-Control-Allow-Origin "*"

Ensuite, lors de la création d'un élément <img>, procédez comme suit:

// jQuery
var img = $('<img src="http://your_server/img.png" crossOrigin="anonymous">')[0]

// or pure
var img = document.createElement('img');
img.src='http://your_server/img.png';
img.setAttribute('crossOrigin','anonymous');
2
Qwerty

J'ai eu le même problème et toutes les images sont hébergées dans le même domaine ... Donc, si quelqu'un a le même problème, voici comment j'ai résolu:

J'avais deux boutons: un pour générer la toile et un autre pour générer l'image à partir de la toile. Cela n'a fonctionné que pour moi, et désolé de ne pas savoir pourquoi, lorsque j'ai écrit tout le code sur le premier bouton. Alors, quand je clique dessus, génère la toile et l'image en même temps ...

J'ai toujours ce problème de sécurité quand les codes étaient sur des fonctions différentes ... = /

2
CarinaPilar

Vous ne pouvez pas mettre d'espaces dans votre identifiant

Mettre à jour

Je suppose que l'image est sur un serveur différent de celui où vous exécutez le script. J'ai pu dupliquer votre erreur en l'exécutant sur ma propre page, mais cela a bien fonctionné dès que j'ai utilisé une image hébergée sur le même domaine. C'est donc lié à la sécurité - mettez l'image sur votre site. Quelqu'un sait pourquoi c'est le cas?

1
Mike Robinson

J'utilise fabric.js et je pourrais résoudre ce problème en utilisant toDatalessJSON au lieu de toDataURL:

canvas.toDatalessJSON({ format: 'jpeg' }).objects[0].src

Edit: Nevermind. Il en résulte que seule l'image d'arrière-plan est exportée au format JPG, sans le dessin au dessus, de sorte que ce n'était pas tout à fait utile.

0
horstwilhelm

Si vous dessinez simplement des images sur une toile, assurez-vous de charger les images du même domaine.

www.example.com est différent de example.com  

Assurez-vous donc que vos images et l'URL que vous avez dans votre barre d'adresse sont les mêmes, que vous soyez sur www ou non.

0
JonathanC