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?

user3465096
fonte
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).

markE
fonte
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>
Annia Martinez
fonte
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"
         })
     });
sknight
fonte
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

mehulmpt
fonte
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"
jdramer
fonte
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.

Prasanna Aarthi
fonte
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();
    });
Ahmad Zahabi
fonte
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;
}

BerlinaLi
fonte
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.

Ludolfyn
fonte
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();
Jeet
fonte