Забруднені полотна можуть не експортуватися


187

Я хочу зберегти своє полотно в імг. Я маю цю функцію:

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

Це дає мені помилку:

Uncaught SecurityError: Не вдалося виконати "toDataURL" на "HTMLCanvasElement": Пошкоджені полотна можуть не експортуватися.

Що я повинен зробити?


У якому браузері? stackoverflow.com/a/21362569/476716 стверджує, що це помилка.
OrangeDog

1
на хром і на firefox
користувач3465096

Відповіді:


180

З міркувань безпеки ваш локальний накопичувач оголошений "іншим доменом" і загрожує полотном.

(Це тому, що ваша найчутливіша інформація, ймовірно, на вашому локальному диску!).

Під час тестування спробуйте такі способи вирішення:

  • Покладіть всі файли, пов’язані зі сторінкою (.html, .jpg, .js, .css тощо) на робочий стіл (а не в підпапки).

  • Опублікуйте свої зображення на веб-сайті, який підтримує обмін між доменами (наприклад, dropbox.com). Не забудьте помістити свої зображення в загальнодоступну папку dropbox, а також встановити прапор перехресного походження під час завантаження зображення (var img = new Image (); img.crossOrigin = "анонімний" ...)

  • Встановіть веб-сервер на свій комп'ютер розробки (на обох веб-серверах IIS та PHP є безкоштовні видання, які добре працюють на локальному комп'ютері).


16
Дякую, налаштування властивості img.crossOrigin допомогло мені!
zumek

5
@markE - я завантажував графічні дані з localStorage замість завантаження з файлу чи будь-якого URL-адреси, після чого робив до нього маніпуляції, як-от додавання тексту. Потім спробували повернути його до localStorage за допомогою toDataURL (). Але він показує "Не вдалося виконати" toDataURL "на" HTMLCanvasElement ": Пошкоджені полотна можуть не експортуватися". У цьому випадку я не використовую жодного файла Exteranl або URL для отримання проблеми міждоменного. Тоді чому це призводить до цієї помилки?
Саджіт

2
@Saijth - Ви можете перевірити шлях, який використовується для зображень. У мене була ця проблема, тому що я тестував безпосередньо доступ до свого локального віртуального сервера через його IP (127.0.xx /), але деякі зображення були пов'язані через домен (localhost /). Одного разу я використав localhost замість цього. Тому переконайтеся, що ви не натрапляєте на щось подібне.
Віктор Д.

1
(1) Перегляньте його з веб-сервера xampp, localhost / файл замість c: / localdisk / file; тоді хром не скаржиться на помилку безпеки. (2) Або використовувати цей прапор при запуску хромування: --allow-file-access-from-files
mosh

1
Просто додайте ще одну можливу проблему: якщо ви намагаєтеся експортувати полотно, яке містить svg з ForeignObject, деякі веб-переглядачі відзначають його як порушене.
HairyFotr

128

У тезі img встановіть crossorigin на Anonymous.

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

61
Але що робити у випадку полотна html5, а не елементів img
graphics123

11
Що стосується елемента полотна, то джерелом проблеми є завжди якесь зображення (або зображення), які ви малюєте на ньому. Тому вам просто потрібно відстежити зображення та встановити його атрибут crossOrigin, як зазначено, перед завантаженням.
Fernando Echeverria

3
Це врятувало мені день!
Чанг

1
Рада допомогти :)
Annia Martinez

9
його 12:00 в офісі, і я знаходжу цю просту відповідь, це чисте щастя
Dheeraj

26

Якщо хтось дивиться на мою відповідь, ви, можливо, у такому стані:

1. Спроба отримати знімок карти в полотні з допомогою OpenLayers (версія> = 3)
2. І розглядати приклад експорту карти
3. Використання ol.source.XYZ , щоб зробити шар карти

Бінго!

Використання ol.source.XYZ.crossOrigin = 'Анонімний' для вирішення вашої плутанини. Або як наступний код:

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

1
фантастичний. Корисно для всіх джерел, як-от TileImage та інших.
Філ

Фатастично! Саме те, що я шукав, просте виправлення демо-версії OpenLayers.
Марк

Я використовую векторні шари плитки і після цього додаю цей джерело до джерела, але він також не працює!
mahdi n75

Саме те, що мені було потрібно :)
Рей

17

Якщо ви використовуєте ctx.drawImage()функцію, ви можете зробити наступне:

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

А у зворотному дзвінку ви тепер можете використовувати ctx.drawImageта експортувати йогоtoDataURL


6
Це для мене не вийшло. Все ще надходить Tainted canvases may not be exported.повідомлення про помилку.
Сем Сверко

1
це працює для мене. Дякую. @SamSverko переконайтеся, що встановіть атрибут перед img.src.
aijogja

14

У моєму випадку я малював на полотні тег із відео. Щоб вирішити помилку зіпсованого полотна, мені довелося зробити дві речі:

<video id="video_source" crossorigin="anonymous">
    <source src="http://crossdomain.example.com/myfile.mp4">
</video>
  • Переконайтеся, що заголовок Access-Control-Allow-Origin встановлено у відповіді джерела відео (належна настройка crossdomain.example.com)
  • Встановіть відеотег, щоб він був crossorigin = "анонімний"

5

Схоже, ви використовуєте зображення з URL-адреси, яка не встановила правильний заголовок Access-Control-Allow-Origin, а отже, і проблему .. Ви можете отримати це зображення з вашого сервера та отримати його з вашого сервера, щоб уникнути проблем CORS ..


Чи можете ви бути більш точними щодо своєї відповіді, тому що я насправді не знаю всього цього поняття. Як я можу отримати це зображення з мого сервера?
користувач3465096

звідки ви отримуєте це зображення, це з вашого сервера чи з іншого?
Prasanna Aarthi

Виходить так: loadImage ("example.jpg", 0, 0, 500, 300); Я можу розмістити URL-адресу або зображення випадкового зображення в одній папці на своєму комп’ютері, її все одно
user3465096

так, але я щойно створив зображення на фарбі, і це все одно те саме
user3465096

1
Я дав Access-Control-Allow-Origin: * для файлу, але все ще він показує помилку
Harikrishnan

5

Я вирішив проблему за допомогою useCORS: trueпараметра

 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

Ознайомтесь із зображенням [увімкнено CORS] [1] від MDN. В основному у вас повинен бути сервер, що розміщує зображення із відповідним заголовком Access-Control-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>

Ви зможете зберегти ці зображення в DOM Storage так, як якщо б вони були подані з вашого домену, інакше у вас виникне проблема безпеки.

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


Хоча це посилання може відповісти на питання, краще включити сюди суттєві частини відповіді та надати посилання для довідки. Відповіді лише на посилання можуть стати недійсними, якщо пов’язана сторінка зміниться. - З огляду
Гоутем Шива

Дякуємо за повідомлення Я просто додаю вміст із посилання MDN :)
BerlinaLi

1

Подібно до відповіді на @ markE - якщо ви хочете створити локальний сервер. У вас не буде цієї помилки на локальному сервері.

Якщо на вашому комп'ютері встановлено PHP:

  1. Відкрийте свій термінал / cmd
  2. Перейдіть у папку, де знаходяться файли вашого веб-сайту
  3. Перебуваючи в цій папці, запустіть команду php -S localhost:3000← Помітьте велику літери "S"
  4. Відкрийте веб-переглядач і в рядку URL-адрес перейдіть до localhost: 3000 . Ваш веб-сайт має працювати там.

або

Якщо на вашому комп’ютері встановлено Node.js:

  1. Відкрийте свій термінал / cmd
  2. Перейдіть у папку, де знаходяться файли вашого веб-сайту
  3. Перебуваючи в цій папці, запустіть команду npm init -y
  4. Бігайте npm install live-server -gабо sudo npm install live-server -gна mac
  5. Запустіть, live-serverі він автоматично відкриє нову вкладку у веб-переглядачі з відкритим веб-сайтом.

Примітка. Не забудьте мати файл index.html у корені вашої папки, інакше у вас можуть виникнути проблеми.


0

Я також вирішив цю помилку, додавши useCORS : true,в свій код на зразок -

html2canvas($("#chart-section")[0], {
        useCORS : true,
        allowTaint : true,
        scale : 0.98,
        dpi : 500,
        width: 1400, height: 900
    }).then();
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.