Разрешение использования изображений и холста из других доменов
HTML предоставляет атрибут crossorigin для изображений, который в сочетании с соответствующим заголовком CORS позволяет использовать изображения, загруженные из внешних источников, в элементе <img> в элементе <canvas>, как если бы они были загружены из текущего домена.
Подробную информацию об использовании атрибута crossorigin см. в разделе Атрибуты настроек CORS.
Безопасность и заражённые холсты
Поскольку пиксели растрового изображения холста могут поступать из различных источников, включая изображения или видео, полученные с других хостов, неизбежны проблемы с безопасностью.
Как только вы нарисуете на холсте данные, загруженные с другого домена без разрешения CORS, холст станет заражённым. Заражённый холст больше не считается безопасным, и любые попытки извлечь данные изображения с холста приведут к исключению.
Если источником внешнего контента является элемент HTML <img> или SVG <svg>, попытка извлечь содержимое холста запрещена.
Если внешний контент получен с помощью изображения, полученного с помощью HTMLCanvasElement или ImageBitMap, и источник изображения не соответствует правилам одного домена, попытки чтения содержимого холста будут заблокированы.
Вызов любого из следующих методов на заражённом холсте приведёт к ошибке:
- Вызов
getImageData()для контекста холста - Вызов
toBlob(),toDataURL()илиcaptureStream()для самого элемента<canvas>
Любая попытка выполнить эти действия при заражении холста вызовет SecurityError. Это защищает пользователей от раскрытия частных данных при использовании изображений для извлечения информации с удалённых веб-сайтов без разрешения.
Сохранение изображения из другого домена
В данном примере мы хотим разрешить загрузку изображений из другого домена и сохранение их в локальном хранилище. Для этого необходимо настроить сервер и написать код для веб-сайта.
Настройка веб-сервера
В первую очередь нам нужен сервер, настроенный для размещения изображений с заголовком Access-Control-Allow-Origin, разрешающим доступ к файлам изображений из других доменов.
Предположим, что наш сайт обслуживается с помощью Apache. Рассмотрим файл конфигурации сервера Apache для изображений CORS от HTML5 Boilerplate, показанный ниже:
<IfModule mod_setenvif.c> <IfModule mod_headers.c> <FilesMatch "\.(avifs?|bmp|cur|gif|ico|jpe?g|jxl|a?png|svgz?|webp)$"> SetEnvIf Origin ":" IS_CORS Header set Access-Control-Allow-Origin "*" env=IS_CORS </FilesMatch> </IfModule> </IfModule>
Короче говоря, эта конфигурация разрешает доступ к графическим файлам (с расширениями ".bmp", ".cur", ".gif", ".ico", ".jpg", ".jpeg", ".png", ".svg", ".svgz" и ".webp") из любого места в интернете.
Реализация функции сохранения
Теперь, когда сервер настроен для разрешения загрузки изображений из других доменов, мы можем написать код, который позволит пользователю сохранять их в локальном хранилище, как если бы они были загружены из того же домена, что и код.
Ключ — использование атрибута crossorigin, установив crossOrigin для элемента HTMLImageElement, в который будет загружено изображение. Это сообщает браузеру запросить доступ к ресурсам из другого домена при загрузке данных изображения.
Запуск загрузки
Код, запускающий загрузку (например, при нажатии пользователем кнопки "Загрузить"), выглядит следующим образом:
function startDownload() { let imageURL = "https://cdn.glitch.com/4c9ebeb9-8b9a-4adc-ad0a-238d9ae00bb5%2Fmdn_logo-only_color.svg?1535749917189"; let imageDescription = "The Mozilla logo"; downloadedImg = new Image(); downloadedImg.crossOrigin = "anonymous"; downloadedImg.addEventListener("load", imageReceived, false); downloadedImg.alt = imageDescription; downloadedImg.src = imageURL; }
Здесь используется жёстко заданный URL (imageURL) и соответствующий описательный текст (imageDescription), но он может быть получен откуда угодно. Для начала загрузки изображения создаётся новый объект HTMLImageElement с помощью конструктора Image(). Затем изображение настраивается для разрешения загрузки из других доменов путём установки атрибута crossOrigin в значение "anonymous" (то есть разрешается загрузка изображения из другого домена без аутентификации). Добавляется обработчик события load для элемента изображения, означающего получение данных изображения. Добавляется альтернативный текст к изображению; хотя <canvas> не поддерживает атрибут alt, значение может быть использовано для установки aria-label или внутреннего содержимого холста.
Наконец, атрибут src изображения устанавливается в URL изображения для загрузки, что запускает загрузку.
Приём и сохранение изображения
Код, обрабатывающий загруженное изображение, находится в методе imageReceived():
function imageReceived() { const canvas = document.createElement("canvas"); const context = canvas.getContext("2d"); canvas.width = downloadedImg.width; canvas.height = downloadedImg.height; canvas.innerText = downloadedImg.alt; context.drawImage(downloadedImg, 0, 0); imageBox.appendChild(canvas); try { localStorage.setItem("saved-image-example", canvas.toDataURL("image/png")); } catch (err) { console.error(`Error: ${err}`); } }
imageReceived() вызывается для обработки события "load" на элементе HTMLImageElement, который получает загруженное изображение. Это событие срабатывает, когда все загруженные данные доступны. Оно начинается с создания нового элемента <canvas>, который мы используем для преобразования изображения в данные URL, и получения доступа к контексту рисования холста 2D (CanvasRenderingContext2D) в переменной context.
Размер холста корректируется для соответствия загруженному изображению, внутренний текст устанавливается в описание изображения, затем изображение рисуется на холсте с помощью drawImage(). Затем холст вставляется в документ, чтобы изображение отобразилось.
Теперь настало время фактически сохранить изображение локально. Для этого используется механизм локального хранилища API веб-хранилища, к которому осуществляется доступ через глобальный объект localStorage. Метод холста toDataURL() используется для преобразования изображения в данные URL-адрес изображения PNG, который затем сохраняется в локальное хранилище с помощью setItem().
См. также
© 2005–2023 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image