Les toiles souillées ne peuvent pas être exportées


200

Je souhaite enregistrer ma toile dans une image. J'ai cette fonction:

function save() {
    document.getElementById("canvasimg").style.border = "2px solid";
    var dataURL = canvas.toDataURL();
    document.getElementById("canvasimg").src = dataURL;
    document.getElementById("canvasimg").style.display = "inline";
}

Cela me donne une erreur:

Uncaught SecurityError: Impossible d'exécuter 'toDataURL' sur 'HTMLCanvasElement': les toiles contaminées ne peuvent pas être exportées.

Que devrais-je faire?


Dans quel navigateur? stackoverflow.com/a/21362569/476716 affirme qu'il s'agit d'un bogue.
OrangeDog

1
sur chrome et sur firefox
user3465096

Réponses:


183

Pour des raisons de sécurité, votre lecteur local est déclaré "autre domaine" et entachera le canevas.

(C'est parce que vos informations les plus sensibles sont probablement sur votre lecteur local!).

Pendant le test, essayez ces solutions de contournement:

  • Placez tous les fichiers liés à la page (.html, .jpg, .js, .css, etc.) sur votre bureau (pas dans des sous-dossiers).

  • Publiez vos images sur un site prenant en charge le partage entre domaines (comme dropbox.com). Assurez-vous de placer vos images dans le dossier public de Dropbox et de définir également l'indicateur d'origine croisée lors du téléchargement de l'image (var img = new Image (); img.crossOrigin = "anonymous" ...)

  • Installez un serveur Web sur votre ordinateur de développement (les serveurs Web IIS et PHP ont tous deux des éditions gratuites qui fonctionnent bien sur un ordinateur local).


19
Merci, la définition de la propriété img.crossOrigin m'a aidé!
zumek

5
@markE - J'ai chargé des données d'image à partir de localStorage au lieu de les charger à partir d'un fichier ou de n'importe quelle URL, puis je les ai manipulées comme l'ajout d'un texte. Ensuite, j'ai essayé de le ramener à localStorage en utilisant toDataURL (). Mais il indique "Impossible d'exécuter 'toDataURL' sur 'HTMLCanvasElement': les toiles corrompues ne peuvent pas être exportées". Dans ce cas, je n'utilise aucun fichier ou URL externe pour obtenir un problème entre domaines. Alors pourquoi cela entraîne-t-il cette erreur?
Sajith

2
@Saijth - Vous voudrez peut-être vérifier le chemin utilisé pour les images. J'ai eu ce problème aussi parce que je testais l'accès direct à mon serveur virtuel local via son IP (127.0.xx /) mais certaines des images étaient liées via le domaine (localhost /). Une fois que j'ai utilisé le localhost à la place, cela a fonctionné. Assurez-vous donc de ne pas tomber sur quelque chose comme ça.
Victor D.

1
(1) Affichez-le à partir du serveur Web xampp, localhost / file au lieu de c: / localdisk / file; alors chrome ne se plaindra pas de l'erreur de sécurité. (2) Ou utilisez cet indicateur lors du démarrage de chrome: --allow-file-access-from-files
mosh

1
Ajout d'un autre problème possible: si vous essayez d'exporter un canevas qui contient un svg avec un ForeignObject, certains navigateurs le marqueront comme corrompu.
HairyFotr

138

Dans la balise img, définissez crossorigin sur Anonymous.

<img crossorigin="anonymous"></img>

63
Mais que faire dans le cas du canevas html5, pas des éléments img
graphics123

11
Dans le cas d'un élément de canevas, la source du problème est toujours avec une image (ou des images) que vous dessinez dessus. Il vous suffit donc de suivre l'image et de définir son attribut crossOrigin comme indiqué, avant de la charger.
Fernando Echeverria

3
Cela m'a sauvé la journée!
Chang

1
Heureux d'aider :)
Annia Martinez

10
son im dans le bureau et 00 heures je trouve cette réponse simple, ce pur bonheur
Dheeraj

28

Si quelqu'un regarde ma réponse, vous êtes peut-être dans cette condition:

1. Essayer d'obtenir une capture d'écran de la carte dans le canevas en utilisant openlayers (version> = 3)
2. Et vu l'exemple d' exportation de la carte
3. Utilisation de ol.source.XYZ pour rendre la couche de carte

Bingo!

En utilisant ol.source.XYZ.crossOrigin = 'Anonymous' pour résoudre votre confusion. Ou comme le code suivant:

     var baseLayer = new ol.layer.Tile({
         name: 'basic',
         source: new ol.source.XYZ({
             url: options.baseMap.basic,
             crossOrigin: "Anonymous"
         })
     });

1
fantastique. Utile pour toutes les sources, comme TileImage et autres.
Phil

Fatastique! Exactement ce que je cherchais moi-même, une solution facile pour une démo OpenLayers que je fais.
Marc

J'utilise des couches de tuiles vectorielles et après ajouter cette propriété à la source, mais cela ne fonctionne pas trop!
mahdi n75 le

Exactement ce dont j'avais besoin :)
Ray

J'utilise ol6. mais ça ne fonctionne pas, pas de changement après l'ajout de cette ligne
Adithya

19

Si vous utilisez la ctx.drawImage()fonction, vous pouvez effectuer les opérations suivantes:

var img = loadImage('../yourimage.png', callback);

function loadImage(src, callback) {
    var img = new Image();

    img.onload = callback;
    img.setAttribute('crossorigin', 'anonymous'); // works for me

    img.src = src;

    return img;
}

Et dans votre rappel, vous pouvez maintenant l'utiliser ctx.drawImageet l'exporter en utilisanttoDataURL


7
Cela n'a pas fonctionné pour moi. Vous recevez toujours le Tainted canvases may not be exported.message d'erreur.
Sam Sverko

2
ça marche pour moi. Merci. @SamSverko assurez-vous de définir l'attribut avant img.src.
aijogja

15

Dans mon cas, je dessinais sur une étiquette de toile à partir d'une vidéo. Pour résoudre l'erreur de toile contaminée, j'ai dû faire deux choses:

<video id="video_source" crossorigin="anonymous">
    <source src="http://crossdomain.example.com/myfile.mp4">
</video>
  • Assurez-vous que l'en-tête Access-Control-Allow-Origin est défini dans la réponse de la source vidéo (configuration correcte de crossdomain.example.com)
  • Définissez le tag vidéo sur crossorigin = "anonymous"

7

J'ai résolu le problème en utilisant l' useCORS: trueoption

 html2canvas(document.getElementsByClassName("droppable-area")[0], { useCORS:true}).then(function (canvas){
        var imgBase64 = canvas.toDataURL();
        // console.log("imgBase64:", imgBase64);
        var imgURL = "data:image/" + imgBase64;
        var triggerDownload = $("<a>").attr("href", imgURL).attr("download", "layout_"+new Date().getTime()+".jpeg").appendTo("body");
        triggerDownload[0].click();
        triggerDownload.remove();
    });

6

On dirait que vous utilisez une image à partir d'une URL qui n'a pas défini l'en-tête correct Access-Control-Allow-Origin et donc le problème .. Vous pouvez récupérer cette image sur votre serveur et l'obtenir sur votre serveur pour éviter les problèmes CORS.


Pourriez-vous être plus précis sur votre réponse, car je ne connais pas vraiment tout ce concept. Comment récupérer cette image sur mon serveur?
user3465096

d'où récupérez-vous cette image, est-ce de votre serveur ou d'un autre?
Prasanna Aarthi

Cela va comme ceci: loadImage ("example.jpg", 0, 0, 500, 300); Je peux mettre une image ou une URL d'image aléatoire dans le même dossier sur mon ordinateur, c'est toujours le même
user3465096

oui, mais je viens de créer une image sur la peinture et c'est toujours la même chose
user3465096

1
J'ai donné Access-Control-Allow-Origin: * pour le fichier, mais il affiche toujours l'erreur
Harikrishnan

3

Découvrez [Image activée CORS] [1] de MDN. Fondamentalement, vous devez avoir un serveur hébergeant des images avec l'en-tête Access-Control-Allow-Origin approprié.

<IfModule mod_setenvif.c>
    <IfModule mod_headers.c>
        <FilesMatch "\.(cur|gif|ico|jpe?g|png|svgz?|webp)$">
            SetEnvIf Origin ":" IS_CORS
            Header set Access-Control-Allow-Origin "*" env=IS_CORS
        </FilesMatch>
    </IfModule>
</IfModule>

Vous pourrez enregistrer ces images sur le stockage DOM comme si elles étaient servies à partir de votre domaine, sinon vous rencontrerez un problème de sécurité.

var img = new Image,
    canvas = document.createElement("canvas"),
    ctx = canvas.getContext("2d"),
    src = "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"; // insert image url here

img.crossOrigin = "Anonymous";

img.onload = function() {
    canvas.width = img.width;
    canvas.height = img.height;
    ctx.drawImage( img, 0, 0 );
    localStorage.setItem( "savedImageData", canvas.toDataURL("image/png") );
}
img.src = src;
// make sure the load event fires for cached images too
if ( img.complete || img.complete === undefined ) {
    img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
    img.src = src;
}


Bien que ce lien puisse répondre à la question, il est préférable d'inclure les parties essentielles de la réponse ici et de fournir le lien pour référence. Les réponses aux liens uniquement peuvent devenir invalides si la page liée change. - De l'avis
Gowtham Shiva

Merci pour l'avis. Je viens d'ajouter le contenu du lien MDN :)
BerlinaLi

1

Juste comme une construction sur la réponse de @ markE - si vous voulez créer un serveur local. Vous n'aurez pas cette erreur sur un serveur local.

Si PHP est installé sur votre ordinateur:

  1. Ouvrez votre terminal / cmd
  2. Naviguez dans le dossier où se trouvent les fichiers de votre site Web
  3. Dans ce dossier, exécutez la commande php -S localhost:3000← Notez le 'S' majuscule
  4. Ouvrez votre navigateur et dans la barre d'URL, accédez à localhost: 3000 . Votre site Web devrait y fonctionner.

ou

Si Node.js est installé sur votre ordinateur:

  1. Ouvrez votre terminal / cmd
  2. Naviguez dans le dossier où se trouvent les fichiers de votre site Web
  3. Dans ce dossier, exécutez la commande npm init -y
  4. Exécuter npm install live-server -gou sudo npm install live-server -gsur un Mac
  5. Exécutez live-serveret il devrait automatiquement ouvrir un nouvel onglet dans le navigateur avec votre site Web ouvert.

Remarque: n'oubliez pas d'avoir un fichier index.html à la racine de votre dossier, sinon vous pourriez avoir des problèmes.


0

J'ai également résolu cette erreur en ajoutant useCORS : true,dans mon code comme -

html2canvas($("#chart-section")[0], {
        useCORS : true,
        allowTaint : true,
        scale : 0.98,
        dpi : 500,
        width: 1400, height: 900
    }).then();
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.