HTML5 Canvas getImageData и одинаковая исходная политика

У меня есть сайт, запущенный на pixie.strd6.com и изображения, размещенные через Amazon S3 с CNAME для images.pixie.strd6.com.

Я хотел бы иметь возможность рисовать эти изображения на холсте HTML5 и вызывать метод getImageData, но он бросает Error: SECURITY_ERR: DOM Exception 18

Я попытался установить window.domain = "pixie.strd6.com", но это не имеет никакого эффекта.

Кроме того, $.get("http://dev.pixie.strd6.com/sprites/8516/thumb.png?1293830982", function(data) {console.log(data)}) также генерирует ошибку: XMLHttpRequest cannot load http://dev.pixie.strd6.com/sprites/8516/thumb.png?1293830982. Origin http://pixie.strd6.com is not allowed by Access-Control-Allow-Origin.

В идеале холст HTML5 не будет блокировать вызов getImageData из поддоменов. Я изучил настройку заголовка Access-Control-Allow-Origin в S3, но не удалось.

Приветствуется любая помощь или обходные пути.

Ответы

Ответ 1

Недавно Amazon объявила о поддержке CORS

Мы рады объявить о поддержке совместного использования ресурсов Cross-Origin (CORS) в Amazon S3. Теперь вы можете легко создавать веб-приложения, которые используют JavaScript и HTML5, чтобы взаимодействовать с ресурсами в Amazon S3, позволяя вам выполнять перетаскивание HTML5 на Amazon S3, показывать ход загрузки или обновлять контент. До сих пор вам нужно было запустить собственный прокси-сервер между вашим веб-приложением и Amazon S3 для поддержки этих возможностей.

Как включить CORS

Чтобы настроить ведро для разрешения запросов с кросс-началом, вы создаете конфигурацию CORS, документ XML с правилами, которые идентифицируют исходные данные, которые вы разрешите получать доступ к вашему ведру, операции (методы HTTP) будут поддерживать для каждого источника, и другую информацию, относящуюся к конкретной операции. Вы можете добавить до 100 правил. Вы добавляете XML-документ в качестве подресурса cors в ведро.

Ответ 2

Одним из возможных решений является использование nginx для работы в качестве прокси. Вот как настроить URL-адреса для http://pixie.strd6.com/s3/ для перехода на S3, но браузер все еще может поверить, что это непересекающийся домен.

location /s3/ {
  proxy_pass http://images.pixie.strd6.com/;
}

Ответ 3

Если вы используете PHP, вы можете сделать что-то вроде:

    function fileExists($path){
        return (@fopen($path,"r")==true);
    }
    $ext = explode('.','https://cgdev-originals.s3.amazonaws.com/fp9emn.jpg');
    if(fileExists('https://cgdev-originals.s3.amazonaws.com/fp9emn.jpg')){
        $contents = file_get_contents('https://cgdev-originals.s3.amazonaws.com/fp9emn.jpg');
        header('Content-type: image/'.end($ext));
        echo $contents;
    }

И получить доступ к изображению с помощью этого php файла, например, если файл называется generateImage.php, вы можете сделать <img src="http://GENERATEPHPLOCATION/generateImage.php"/>, а внешний URL-адрес изображения может быть параметром get для файла

Ответ 4

Недавно я наткнулся на $.getImageData, Макс Новакович. На странице есть несколько аккуратных демонстраций извлечения и работы с фотографиями Flickr, а также некоторые примеры кода.

Он позволяет вам получить изображение в JavaScript-манипулируемой форме с произвольного сайта. Он работает, добавив script на страницу. Затем script запрашивает изображение с сервера Google App Engine. Сервер извлекает запрошенное изображение и передает его преобразование в base64 в script. Когда script получает base64, он передает данные в обратный вызов, который затем может нарисовать его на холст и начать с ним общаться.

Ответ 5

В прошлом Amazon S3 не позволял вам изменять или добавлять заголовки HTTP-заголовков access-control-allow-source и access-control-allow-credentials, поэтому было бы лучше переключиться на другую службу, например, Rackspace Cloud Файлы или какая-либо другая служба, которая делает.

Добавьте или измените заголовки HTTP следующим образом:

access-control-allow-origin: [your site]
access-control-allow-credentials: true

Подробнее см. http://www.w3.org/TR/cors/#use-cases.

Использование службы, которая позволяет изменять заголовки HTTP, полностью решает ту же проблему происхождения.

Ответ 6

Для людей, которые не используют S3, можно попытаться создать прокси-сервер изображения, который кодирует файл изображения и переносит его в объект JSON.

Затем вы можете использовать JSONP, который поддерживает кросс-домен, чтобы получить объект JSON и назначить данные изображения img.src.

Я написал пример кода прокси-сервера изображения с Google App Engine. https://github.com/flyakite/gae-image-proxy

Объект JSON возвращается в формате, подобном этому

{ 
  'height': 50, 
  'width' : 50, 
  'data'  : 'data:image/jpeg;base64,QWRarjgk4546asd...QWAsdf'
} 

"Данные" - это данные изображения в формате base64. Присвойте его изображению.

img.src = result.data;

Теперь изображение становится "чистым" для вашего холста.

Ответ 7

Чтобы отредактировать права на ведро S3:

1) Войдите в консоль управления AWS и откройте консоль Amazon S3 на https://console.aws.amazon.com/s3/

2) В списке "Ковши" откройте ведро, свойства которого вы хотите просмотреть, и нажмите "добавить конфигурацию CORS"

amazon-screen-shot

3) Напишите правила, которые вы хотите добавить между тегами <CORSConfiguration>

<CORSConfiguration>
  <CORSRule>
    <AllowedOrigin>*</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>*</AllowedHeader>
  </CORSRule>
</CORSConfiguration>

Подробнее о правилах вы можете узнать по адресу http://docs.aws.amazon.com/AmazonS3/latest/dev/cors.html

4) Укажите crossorigin = 'anonymous' на изображении, которое вы будете использовать в своем холсте

Ответ 8

Это поведение пошагово. По спецификации HTML5, как только вы нарисуете крестообразное изображение на холст, он грязный, и вы больше не можете читать пиксели. Сравнение совпадений сравнивает схему, полностью квалифицированный хост и в браузерах, отличных от IE, порт.

Ответ 9

Просто столкнулся с той же проблемой. Я узнал о CORS, которые могут быть полезны.

http://html5-demos.appspot.com/static/html5-whats-new/template/index.html#14

Это не сработало для меня, так как я пытаюсь манипулировать изображением Flickr. Итак, я все еще ищу решение.