javascriptのみで完結するダウンロード処理の実装方法

ちょっと調べてみたけどどれも面倒なことをやっているのでメモ
せめて関数呼んだらダウンロード処理が始まる程度のことはやりたいですね
最新版のIE、Edge、Chrome、FireFoxで実行確認
IEだと2回ダウンロードされていたので修正。
I可読性が高くなるようにリライト









実装手順


手順としては以下の様な感じです

1.ダウンロード用のデータ(Blob)を作成する
2.linkをjs上で作成する
3.作成したリンクをクリック

3が思ったより面倒くさかった



サンプル


See the Pen File download Sample by ninomae-makoto (@ninomae-makoto) on CodePen.




function downloadtest() {
    var data = document.getElementById("data").value;
    var downloadFileName = "downloadtest.txt";

    var blob = new Blob([data], { "type": "application/x-msdownload" });
    // ダウンロード処理
    if (window.navigator.msSaveBlob) { 
        // IE, Edge
        window.navigator.msSaveOrOpenBlob(blob, downloadFileName); 
    }
    else {
        // Chrome, FireFox
        var link = document.createElement('a');
        link.setAttribute("download", downloadFileName);
        link.href = URL.createObjectURL(blob);
        var evt = document.createEvent( "MouseEvents" );
        evt.initEvent( "click", false, true );
        link.dispatchEvent( evt );
    }
}


データ(今回は文字列)をBlobデータへ変換したあとダウンロード処理をおこなう。

Blob URL Schemeと呼ばれるもの
https://gist.github.com/nishimunea/5d06bf899198eb104238


補足



何かよくわからない処理が記述してあるのはブラウザ間で挙動が違ったからです。はい。

Chrome


一度リンクにしたあとそれをクリックするといったアプローチを取る。
link.click();
でダウンロードが始まる。
だが他のブラウザがでは使用できない。

FireFox


link.click();が使えない(http://language-and-engineering.hatenablog.jp/entry/20090907/p1 参照)
イベントを作成してイベントを発火する形ならダウンロード可能。

IE

dispatchEventの代わりにfireEventを使う必要があるらしい。
直接Blobデータをダウンロードできる。

Edge

dispatchEventだとファイル名がおかしくなる(指定できない?)
直接Blobデータをダウンロードできる。


以上よりIE, EdgeはmsSaveOrOpenBlobで直接ダウンロード, Chrome, FirefoxはdispatchEventでリンクのクリックイベントを発火できる。

Blobとは?

ファイルみたいなものという認識でいいかな?
https://developer.mozilla.org/ja/docs/Web/API/Blob
今回の例はテキストだけど画像もいけるはず



みんなで仲良く手を取り合って発展させていくって誰か言ってたじゃないですかー!
MS内ですら挙動違うじゃないですかー!!

ブログのノリが変わる程度には時間が立ったが特に変化はないようだ...

2016年5月8日日曜日