Edited at

jsでダウンロードを実装した話

こういうコードを書くたび忘れそうと思うので備忘録。

コードの方で作成したjsonオブジェクトをファイルに書き込み、ダウンロードするボタンを作りました。

ボタンクリックすると遷移なしでダウンロードが始まる感じです。

参考にしたサイトはこちら

http://kuroeveryday.blogspot.jp/2015/07/javascript-upload-download.html

https://elearn.jp/jmemo/javascript/memo-325.html

https://webdesign.tutsplus.com/ja/tutorials/quick-tip-using-the-html5-download-attribute--cms-23880

少々古いですが…


さっそく実装

HTML5ではdownload属性にファイル名、hrefにファイルパスを指定することでファイルをダウンロードできます。

<a href="download/acme-doc-2.0.1.txt" download="Acme Documentation (ver. 2.0.1).txt">Download Text</a>

しかしこれで僕がやりたいことをやるには


  • ファイルを適当な場所に作成、保存

  • その保存場所をhrefに指定してダウンロード

と二度手間になってしまう。

ボタンを押すだけで、コードの別の部分で作ったjsonをそのままファイルに書き込み、保存し、ダウンロードしたかったんです。

探したらありました。


html側

<button type="button" ng-click="downLoadJson();">ダウンロード</button>



js側

$scope.downLoadJson = function () {

//ファイルを作ってダウンロードします。
var resultJson = JSON.stringify($scope.jsonObj);
var downLoadLink = document.createElement("a");
downLoadLink.download = $scope.fileName;
downLoadLink.href = URL.createObjectURL(new Blob([resultJson], {type: "text.plain"}));
downLoadLink.dataset.downloadurl = ["text/plain", downLoadLink.download, downLoadLink.href].join(":");
downLoadLink.click();
}

上記のdownload属性をhtmlで設定する代わりにjsでcreateElementを使って設定しています。

気になる(というかぱっと見でよくわからなかった)のは

URL.createObjectURL(new Blob([resultJson], {type: "text.plain"}))

downLoadLink.dataset.downloadurl = ["text/plain", downLoadLink.download, downLoadLink.href].join(":");

の部分。


URL.createObjectURLについて

こちらにいろいろ書いてありました。

http://hakuhin.jp/js/blob_url_scheme.html

Blob URL Schemeというものを生成するメソッドだそうです。

要するにオブジェクトを指定するとそこからランダムな文字列動的に生成してURLに使うもので、

URLにディレクトリ名が入らないので機密性が保証されると。

具体的な生成法は不明です。ていうかわかったらまずいですよね…

ちなみに大容量のデータでも重くならないらしいです。この辺はよくわからないので要調査。


dataset.downloadurlについて

https://developer.mozilla.org/ja/docs/Web/API/HTMLElement/dataset

こちらのサイトによると、


カスタムdata属性 (data-*)のセットされたすべての要素に対して、読み取り専用のプロパティを提供するためのものです。


とのこと。

これ以外の説明はちょっと見当たらなかったのでこれも要調査