Hebikuzure's Tech Memo

2012年12月16日

File API で作成した blob をダウンロードする

Filed under: Internet Explorer — hebikuzure @ 5:30 午後

この記事は “HTML5 Advent Calendar 2012” の16日目の記事です。他の記事もぜひご覧ください。


HTML5 では BlobBuilder オブジェクトを作成して、ファイルをメモリ上に読み込んだり、あるいはユーザーの入力やサーバーから取得したデータを元にしてメモリ上にファイルの内容を作成することが可能です。また作成した Blob は XML HTTP Request (XHR) の FormData としてサーバーにアップロードすることも可能です。

ではメモリ上の Blob をローカルに保存したい場合、どうすればよいでしょうか。Web ページのスクリプトから直接ローカルのファイル システムを操作する File System API (File API: Directories and SystemFile API: Writer) の標準化について議論が進められており、これを利用すればローカルのアプリケーションと同じようなエクスペリエンスで Web ページから blob データのダウンロードを行えそうです。しかし現時点ではブラウザー間での実装の差が大きく、実験的な用途以外では利用しにくいかもしれません。

そこで別の方法として、作成した Blob に対して createObjectURL メソッドで URL を生成し、その URL をリンク先にすることで Blob の内容をローカルにダウンロードさせることが考えられます。この方法の簡単なサンプルを以下に示します。

<script type="text/javascript">
    function startDownload() {
        var text = document.getElementById("text").value;
        var blob = new Blob([text]);
        var url = window.URL.createObjectURL(blob);
        document.getElementById(‘download’).href = url;
    }
</script>
<textarea id="text" placeholder="文字を入力してください。"></textarea><br />
<p>下のリンクをクリックしてください</p>
<p><a href=# id="download" onclick="startDownload()">ダウンロード</a></p>

image

この方法は簡単な操作で実現できるので実用的に見えますが、いくつか難点があります。1つ目はダウンロードされるファイルのファイル名を制御できない点、2つ目は Blob の内容によってダウンロードされたファイルがブラウザーでそのまま開かれるか、ファイルシステムへの保存のダイアログが表示されるか変わってしまう点、そして3つ目は Internet Explorer では createObjectURL メソッドで生成された URL が通常のリンクに利用できない点です (Internet Explorer ではcreateObjectURL メソッドで生成された URL は src=”…” で指定するようなサブ ダウンロードのアドレスとしてのみ有効です) 。

Internet Explorer 10では File API がサポートされ、Blob も取り扱うことができるようになりましたが、 createObjectURL メソッドで生成された URL についての制限があるため、Chrome や Firefox のように上記のサンプルのような方法で Blob をローカルにダウンロードできません。その代りなのでしょうか、Internet Explorer では DOM メソッドとして msSaveBlobmsSaveOrOpenBlob が用意されています。

  • var retVal = Navigator.msSaveBlob(blob, defaultName);
  • var retVal = Navigator.msSaveOrOpenBlob(blob, defaultName);

いずれも第1引数はダウンロードする blob オブジェクト、第2引数は保存する場合のファイル名の初期値です。2つのメソッドの違いは、msSaveBlob ではファイルを保存するかキャンセルするかの選択肢が表示され、msSaveOrOpenBlob ではそれに加えて開くオプションも提供される事です。

image
msSaveBlob の場合

image
msSaveOrOpenBlob の場合

msSaveBlob メソッドを使って前のサンプルを Internet Explorer 10 にも対応させると、以下のようになります。

<script type="text/javascript">
    function startDownload() {
        var text = document.getElementById("text").value;
        var blob = new Blob([text]);

        if (window.navigator.msSaveBlob) {
            window.navigator.msSaveBlob(blob, ‘BlobFile.txt’);
        } else {
            var url = window.URL.createObjectURL(blob);
            document.getElementById(‘download’).href = url;
        }
    }
</script>
<textarea id="text" placeholder="文字を入力してください。"></textarea>
<p>
    下のリンクをクリックしてください
</p>
<p>
    <a href=# id="download" onclick="startDownload()">ダウンロード</a>
</p>
<p>
    Internet Explorer 10ではテキストがファイルとしてダウンロードされます。<br />
    Chrome と Firefox ではテキストがブラウザーで表示されます。
</p>

image

 

なおそれぞれのメソッドの実行した際の Internet explorer 10の挙動は、以下のような HTTP 応答ヘッダーを受信した場合と同じになります。

msSaveBlob

Content-Length: <blob.size>
Content-Type: <blob.type>
Content-Disposition: attachment;filename=<defaultName>
msSaveOrOpenBlob
Content-Length: <blob.size>
Content-Type: <blob.type>
Content-Disposition: attachment;filename=<defaultName>
X-Download-Options: noopen </ dd>

Web アプリケーションの実用的な範囲が広がるにつれ、こうした Web ページからのダウンロードへのニーズも大きくなるでしょう。現在はまだ十分な互換性と相互運用性があるとは言えない状況ですので、ターゲット ブラウザーを絞るか、ブラウザーごとに可能な手段を利用するよう分岐させるか、難しい判断で出てくる部分です。しかしアプリケーションのユーザー エクスペリエンスを良好にするためには重要な部分であり、今後の各ベンダーの実装の進捗や、標準化の議論に期待していきたいと思います。


参考情報

1件のコメント »

  1. ファイル名をdownload属性を使えば設定できます

    コメント by nanashi — 2012年12月27日 @ 8:50 午前


RSS feed for comments on this post. TrackBack URI

コメントを残す

WordPress.com Blog.