S3(CloudFront)の画像をcanvasで使いたいっ!

タイトルのままですが、外部のサーバーにアップロードされている画像をcanvasに入れようと思ったら、色々と制限があるようなので調べてみました。

js実装

何も気にせずに書くとすれば、

const url = 'https:///example.com/test.jpg'; // s3(もしくはCloudFront)の画像URL

let image = new Image;
image.addEventListener("load", imageLoaded, false);
image.src = url;

function imageLoaded() {
  let canvas = document.createElement("canvas");
  let context = canvas.getContext("2d");

  canvas.width  = image.width;
  canvas.height = image.height;

  context.drawImage(image, 0, 0);

  const file = canvas.toDataURL("image/jpeg");
}

と、こんな感じでfileがダウンロードできるはずなんですが、外部のファイルはそのままだとjsで開けないぽいですね。

Cross-Origin Resource Sharing(CORS)

s3 > アクセス権限 > バケットポリシーを編集します。

<CORSConfiguration>
 <CORSRule>
   <AllowedOrigin>https://example.com</AllowedOrigin>
   <AllowedMethod>GET</AllowedMethod>
   <AllowedHeader>*</AllowedHeader>
 </CORSRule>
</CORSConfiguration>

最低限これだけ書けば、https://example.com のjsで画像が扱えるようになります。

js修正

ここまでで取得できると思いきや・・取得できないので調べた結果

let image = new Image;

image.crossOrigin = "Anonymous"; // <-- 追加

image.addEventListener("load", imageLoaded, false);
image.src = url;

crossOriginの設定を追加して読み込みに成功しました。

参考

Cross-Origin Resource Sharing (CORS) – Amazon Simple Storage Service
画像とキャンバスをオリジン間で利用できるようにする – HTML: HyperText Markup Language | MDN