Почему canvas.toDataURL() выдает исключение безопасности?
Неужели я недостаточно спал или что? Этот следующий код
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 where the error happens:
window.open(frame.toDataURL("image/png"));
}
выбрасывает эту ошибку:
SECURITY_ERR: DOM Exception 18
Нет, это не должно работать! Может кто-нибудь объяснить это, пожалуйста?
Ответы
Ответ 1
В specs говорится:
Всякий раз, когда метод toDataURL() элемент холста, чей исходный чистый флаг установлено значение false, метод должен вызвать исключение SECURITY_ERR.
Если изображение идет с другого сервера, я не думаю, что вы можете использовать toDataURL()
Ответ 2
Настройка атрибута cross origin для объектов изображения, обработанных для меня (я использовал 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';
Для тех, кто использует fabricjs, здесь, как исправлять 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;
};
Ответ 3
Если изображение размещено на хосте, который устанавливает любой из Access-Control-Allow-Origin или Access-Control-Allow-Credentials, вы можете использовать Cross Origin Resource Sharing (CORS). Подробнее см. здесь (атрибут crossorigin).
Другой вариант - для вашего сервера иметь конечную точку, которая извлекает и обслуживает изображение. (например, http://your_hosthttps://stackoverflow.com/endpoint?url=URL)
Недостатком этого подхода является латентность и теоретически ненужная выборка.
Если будет больше альтернативных решений, мне будет интересно услышать о них.
Ответ 4
Кажется, есть способ предотвратить, если хостинг изображений может предоставить следующие заголовки HTTP для ресурсов изображения, а браузер поддерживает CORS:
access-control-allow-origin: *
access-control-allow-credentials: true
Здесь говорится: http://www.w3.org/TR/cors/#use-cases
Ответ 5
У меня была такая же проблема, и все изображения размещались в одном домене... Итак, если у кого-то такая же проблема, вот как я решил:
У меня было две кнопки: одна для создания холста, а другая - для создания изображения с холста. Это работало только для меня, и жаль, что я не знаю, почему, когда я написал весь код на первой кнопке. Поэтому, когда я нажимаю, он генерирует холст и изображение одновременно...
У меня всегда есть эта проблема безопасности, когда коды были на разных функциях... =/
Ответ 6
Наконец, я нашел решение. Просто добавьте crossOrigin
в качестве третьего параметра в fromURL
func
fabric.Image.fromURL(imageUrl, function (image) {
//your logic
}, { crossOrigin: "Anonymous" });
Ответ 7
Вы не можете помещать пробелы в свой идентификатор
Обновление
Я предполагаю, что изображение находится на другом сервере, чем где вы выполняете script. Я смог дублировать вашу ошибку при запуске на моей собственной странице, но она отлично работала в тот момент, когда я использовал изображение, размещенное в том же домене. Так что это связано с безопасностью - поместите изображение на свой сайт. Кто-нибудь знает, почему это так?
Ответ 8
Мне удалось заставить его работать, используя это:
Напишите это в первой строке вашего .htaccess
на исходном сервере
Header add Access-Control-Allow-Origin "*"
Затем при создании элемента <img>
сделайте это следующим образом:
// 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');
Ответ 9
Если вы просто рисуете некоторые изображения на холсте, убедитесь, что вы загружаете изображения из одного домена.
www.example.com отличается от example.com
Поэтому убедитесь, что ваши изображения и URL-адрес, которые у вас есть в адресной строке, одинаковы, www или нет.
Ответ 10
Я использую fabric.js и могу решить эту проблему, используя toDatalessJSON вместо toDataURL:
canvas.toDatalessJSON({ format: 'jpeg' }).objects[0].src
Редактировать: Nevermind. Это приводит только к тому, что фоновое изображение экспортируется в JPG, без рисунка сверху, так что в конце концов оно оказалось не совсем полезным.