Tech Sketch Bucket of Technical Chips by TIS Inc.

DataURLとCanvasとドメイン

Pocket

HTML5の一要素として利用可能なCanvasのtoDataURL()メソッドからRFC2397("The data URL scheme")なども参照しつつ、DataURL形式の利用とドメインの制約などを取り上げます。


Canvasとdataurl

HTML5の一要素としてでお馴染みになりつつあるCanvasはブラウザ上で画像や図を作成することを可能にしたものです。
このCanvasにはtoDataURL()というメソッドがあります。
このメソッドはCanvasに描画されている画像をdataurl化して取得することができます。

ところで、dataurlとはなんでしょう?

The "data" URL scheme

data urlに関しては固い文書で言えばRFC2397で定義されています。
RFC2397のabstructによると以下のように記述されています。

1. Abstract
A new URL scheme, "data", is defined. It allows inclusion of small
data items as "immediate" data, as if it had been included
externally.

利用する上では

  • 新しい "data:" というスキーマで定義されている
  • 小さなデータを即時に利用可能にする
  • 別のファイルのように(通常のファイルへのリンクと同様に)利用できる。

といったところでしょうか。

data urlは以下のようなフォーマットです。

RFCに掲載されている具体的な例だと以下のような例が挙げられています。
以下は、リンク先をdata urlにしています。IEではリンク先は見られないようです。

テキストのdata url
data:,A%20brief%20note

画像(gif)のdata url
data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAwAAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFzByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSpa/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJlZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uisF81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PHhhx4dbgYKAAA7

通常の用途だと小さいアイコンなどをdataurl化して画像を表示する感じになるかと思います。(こちらの画像はdataurl化したものを表示しており、リンク先もdataurlにしてます。)

以下はdataurlによって表示している画像。


と、いったようにdataurl化によってHTML内に文字列を埋め込むことで画像を表示することができます。

dataurlの現実

dataurlが提案された時点ではRFC内でもsmall dataと出てくる程度に小さいデータ向けの想定だったようですが、Canvasの登場とそのtoDataURL()メソッドの登場でdataurlは小さいデータをHTMLに埋め込む用途だけでなくCanvasのデータの出力などの用途で利用されるようになり、それなりに大きなデータも取り扱うようになりました。(IE9だとdataurlで4GBまで取り扱えるようです。)

現在のところdataurlはデータ(特に画像データ)をHTMLに埋め込んだり、Canvasから簡単に取得できるといったところで利用されていると思われます。

通常では"dataurl化した小さな画像"をHTMLに組み込むことはページを高速表示することに役に立ちます。(RFCでもsmall data items as "immediate" dataといってますし)
しかしながら、"dataurl化した大きな画像"を組み込むとその巨大な画像データを読み込まない限り画像より後ろのHTMLが読み込まれないということが発生します。

要は大きなデータをHTMLに組み込んでサーバから直接返すような実装は避けるべきです。

Canvasへのデータ読み込みとドメイン

Canvasへのデータ読み込みはドメインが異なっていても可能です。
読み込み済みのImageをdrawImage()やputImageData()などでCanvasに描画することでCanvas上に画像データを反映するためImageタグなどと同様な挙動であり当然といえば当然です。

しかし、他のドメインから読み込みされたデータを書き込んだcanvasは前述のtoDataURL()のようなDataURL化した出力やgetImageData()のような画像取得などの出力処理を実行すると以下のようなエラーが発生して正しく動作することができません。

Chrome

Uncaught Error: SECURITY_ERR: DOM Exception 18

Firefox

エラー: SecurityError: The operation is insecure.

これはエラーの文言通りセキュリティ上の問題です。
他のドメインやローカルファイルのデータを勝手に送信されないようにするためだと思われます。
上記のエラーメッセージで検索すると多くの情報が出てくるので興味がある方は調べてみるとよいと思います。

対策

というわけで、Canvasに読み込んだ画像を出力するためにはページと同一ドメインである必要があるようです。
そのため、別ドメインにあるAmazon S3のようなクラウドストレージの画像をCanvasに取得したあと出力するためには何らかの小細工が必要です
そのあたりを実際にやってみた例を別の記事で紹介しようと思います。

参考

The data URL scheme
MSDN blogs: IE9 Beta Minor Changes List
html5jp

エンジニア採用中!私たちと一緒に働いてみませんか?