Telas contaminadas não podem ser exportadas


187

Quero salvar minha tela em um img. Eu tenho esta função:

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

Isso me dá erro:

Não detectado SecurityError: falha ao executar 'toDataURL' em 'HTMLCanvasElement': telas contaminadas não podem ser exportadas.

O que devo fazer?


Em que navegador? stackoverflow.com/a/21362569/476716 afirma que este é um erro.
— OrangeDog

1
no chrome e no firefox
— user3465096

Respostas:


180

Por motivos de segurança, sua unidade local é declarada como "outro domínio" e manchará a tela.

(Isso ocorre porque suas informações mais sensíveis provavelmente estão em sua unidade local!).

Durante o teste, tente estas soluções alternativas:

  • Coloque todos os arquivos relacionados à página (.html, .jpg, .js, .css, etc) na área de trabalho (não nas subpastas).

  • Publique suas imagens em um site compatível com compartilhamento entre domínios (como dropbox.com). Coloque suas imagens na pasta pública do dropbox e também defina o sinalizador de origem cruzada ao baixar a imagem (var img = nova imagem (); img.crossOrigin = "anônimo" ...)

  • Instale um servidor da web no seu computador de desenvolvimento (os servidores da Web IIS e PHP possuem edições gratuitas que funcionam bem em um computador local).


16
Obrigado, configurar a propriedade img.crossOrigin me ajudou!
— Zumek

5
@markE - Carreguei dados de imagem do localStorage em vez de carregar do arquivo ou de qualquer URL, depois fiz alguma manipulação, como adicionar um texto. Em seguida, tentei devolvê-lo ao localStorage usando toDataURL (). Mas mostra "Falha ao executar 'toDataURL' em 'HTMLCanvasElement': telas contaminadas não podem ser exportadas". Nesse caso, não estou usando nenhum arquivo ou URL exteranl para obter um problema entre domínios. Então, por que está resultando nesse erro?
— Sajith

2
@Saijth - Convém verificar o caminho usado para as imagens. Eu também tive esse problema porque estava testando acesso direto ao servidor virtual local por meio do IP (127.0.xx /), mas algumas das imagens foram vinculadas pelo domínio (localhost /). Uma vez eu usei o host local em vez disso funcionou. Portanto, verifique se você não está se deparando com algo assim.
— Victor D.

1
(1) Veja-o no xampp webserver, localhost / file em vez de c: / localdisk / file; o chrome não reclamará sobre o erro de segurança. (2) Ou use esta flag ao iniciar o chrome: --allow-file-access-from-files
— mosh

1
Apenas adicionando outro possível problema: se você estiver tentando exportar uma tela que contém um svg com um ForeignObject, alguns navegadores a marcarão como contaminada.
— 7898 HairyFotr

128

Na tag img, configure crossorigin para Anonymous.

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

61
Mas o que fazer no caso de canvas html5, elementos não img
— graphics123

11
No caso de um elemento de tela, a fonte do problema está sempre com alguma imagem (ou imagens) que você está desenhando nela. Então, você só precisa rastrear a imagem e definir seu atributo crossOrigin conforme indicado, antes de carregá-la.
— Fernando Echeverria

3
Isso salvou meu dia!
— 7282 Chang

1
Happy to help :)
— Annia Martinez

9
sua im 12:00 no escritório e eu encontrar essa resposta simples, isso é pura felicidade
— Dheeraj

26

Se alguém visualizar minha resposta, talvez você esteja nesta condição:

1. Tentando obter uma captura de tela do mapa na tela usando openlayers (versão> = 3)
2. E visualizou o exemplo da exportação de mapa
3. Usando ol.source.XYZ para renderizar a camada do mapa

Bingo!

Usando ol.source.XYZ.crossOrigin = 'Anônimo' para resolver seu confuso. Ou como o seguinte código:

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

1
fantástico. Útil para todas as fontes, como TileImage e outras.
— 22418 Phil

Fatastic! Exatamente o que eu estava procurando, solução fácil para uma demonstração do OpenLayers que estou fazendo.
— Marc

Estou usando camadas de ladrilhos vetoriais e depois adiciono essas propriedades à fonte, mas não está funcionando também!
— mahdi n75 29/04

Exatamente o que eu precisava :)
— Ray

17

Se você estiver usando a ctx.drawImage()função, poderá fazer o seguinte:

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

E no seu retorno de chamada, agora você pode usá ctx.drawImage-lo e exportá-lo usandotoDataURL


6
Isto não funcionou para mim. Ainda recebendo a Tainted canvases may not be exported.mensagem de erro.
— Sam Sverko 19/09/19

1
funciona para mim. obrigado. @SamSverko certifique-se de definir o atributo antes de img.src.
— aijogja

14

No meu caso, eu estava desenhando uma tag de tela de um vídeo. Para resolver o erro de tela contaminada, tive que fazer duas coisas:

<video id="video_source" crossorigin="anonymous">
    <source src="http://crossdomain.example.com/myfile.mp4">
</video>
  • Verifique se o cabeçalho Access-Control-Allow-Origin está definido na resposta da fonte de vídeo (configuração adequada de crossdomain.example.com)
  • Defina a tag de vídeo como crossorigin = "anonymous"

5

Parece que você está usando uma imagem de um URL que não definiu o cabeçalho correto de Controle de acesso-permissão de origem e, portanto, o problema. Você pode buscar essa imagem no servidor e obtê-la no servidor para evitar problemas de CORS.


Você poderia ser mais preciso sobre sua resposta, porque eu realmente não conheço todo esse conceito. Como obtenho essa imagem do meu servidor?
— user3465096

de onde você está buscando essa imagem, é do seu servidor ou de outro?
— Prasanna Aarthi

É assim: loadImage ("example.jpg", 0, 0, 500, 300); Eu posso colocar url imagem aleatória ou imagem na mesma pasta no meu computador, o seu ainda o mesmo
— user3465096

sim, mas eu apenas criei uma imagem na pintura e ainda é a mesma
— user3465096

1
Eu dei Access-Control-Allow-Origin: * para o arquivo, mas ainda está mostrando o erro
— Harikrishnan

5

Resolvi o problema usando a useCORS: trueopção

 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();
    });

3

Confira [imagem ativada para CORS] [1] no MDN. Basicamente, você deve ter um servidor que hospeda imagens com o cabeçalho apropriado Access Control Control Allow Allow Origin.

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

Você poderá salvar essas imagens no armazenamento DOM como se elas fossem veiculadas em seu domínio, caso contrário, você terá um problema de segurança.

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


Embora esse link possa responder à pergunta, é melhor incluir aqui as partes essenciais da resposta e fornecer o link para referência. As respostas somente para links podem se tornar inválidas se a página vinculada for alterada. - Do comentário
— Gowtham Shiva

Obrigado pelo aviso. Eu só adicionar o conteúdo a partir do link MDN :)
— BerlinaLi

1

Assim como a resposta da @ markE - se você deseja criar um servidor local. Você não terá esse erro em um servidor local.

Se você possui o PHP instalado no seu computador:

  1. Abra seu terminal / cmd
  2. Navegue até a pasta onde estão os arquivos do site
  3. Enquanto estiver nesta pasta, execute o comando php -S localhost:3000 ← Observe o 'S' maiúsculo
  4. Abra o navegador e, na barra de URL, vá para localhost: 3000 . Seu site deve estar sendo executado lá.

ou

Se você tiver o Node.js instalado no seu computador:

  1. Abra seu terminal / cmd
  2. Navegue até a pasta onde estão os arquivos do site
  3. Enquanto estiver nesta pasta, execute o comando npm init -y
  4. Executar npm install live-server -gousudo npm install live-server -g em um mac
  5. Execute live-servere ele deve abrir automaticamente uma nova guia no navegador com o site aberto.

Nota: lembre-se de ter um arquivo index.html na raiz da sua pasta; caso contrário, você pode ter alguns problemas.


0

Eu também resolvi esse erro adicionando useCORS : true,no meu código como -

html2canvas($("#chart-section")[0], {
        useCORS : true,
        allowTaint : true,
        scale : 0.98,
        dpi : 500,
        width: 1400, height: 900
    }).then();
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.