msSaveBlob,Data URI SchemeおよびURL.createObjectURLによるデータ保存
jsでデータ保存(download)する方法として以下の方法を試す
- navigator.msSaveBlob
-
利用できるのはIEだけ(Blob と `navigator.msSaveBlob` を使ってファイルをローカルに保存する)
var blob = new Blob(["blobデータ"]); window.navigator.msSaveBlob(blob, "filename.txt"); //ダウンロードダイアログが表示
Blobデータをダウンロードフォルダに保存する。
navigator.msSaveOrOpenBlob
という関数もあり、こちらはすぐ開くか保存するかを選択する。 - Data URI Scheme
-
多くのブラウザで動作する
<a href="data:application/octet-stream;base64,..." download="filename.txt">download</a>
をクリックさせることでダウンロード。Base64化したデータを直接記述する。var data = "Data URI Schemeによるダウンロード", base64 = btoa(unescape(encodeURIComponent(data))), a = document.createElement('A'); a.download = 'filename.txt'; a.href = 'data:application/octet-stream;base64,' + encodeURIComponent(base64); document.body.appendChild(a); a.click(); //自動ダウンロード document.body.removeChild(a);
リンク先のURLはデータの長さに比例(4/3倍)する。データが大きいとメモリを大量消費する
- URL.createObjectURL
- msSaveBlobが利用可能なら使う
- 不可の場合、URL.createObjectURL()を利用可能ならば使う
- どちらも不可の場合はData URI Schemeを利用する
利用できるのはwindow.URLがあるブラウザのみ(URL.createObjectURL() - Web APIs | MDN)
URL.createObjectURL(file)
とすると、ブラウザがBlobデータをランダムな値がついたobjectURLに変換する
var data = "URL.createObjectURL()によるダウンロード",
url = URL.createObjectURL(new Blob([data])),
a = document.createElement('A');
alert(url);
a.download = 'filename.txt';
a.href = url;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
こちらは大きいデータでも快適に動作する。IEの場合、ローカルな環境(file://...)では動作しない
切り替えて利用する
var saveText = function(str, filename) {
var uri, a;
if (navigator.msSaveBlob) {
navigator.msSaveBlob(new Blob([str]), filename);
return;
}
if (window.URL && window.URL.createObjectURL) {
uri = URL.createObjectURL(new Blob([str]));
} else {
uri = 'data:application/octet-stream;base64,' +
encodeURIComponent(btoa(unescape(encodeURIComponent(str))));;
}
a = document.createElement('A');
a.href = uri;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};
saveText("保存したいテキスト", "filename.txt");
テキストだけではなく任意のデータ(バイト列)を保存したい場合には多少工夫が必要になる。 具体的には、Data URI Schemeの作成時の処理が変化している。 非同期実行にはなるが、この部分にBlobとFileReader.prototype.readAsDataURL()
を使用してもよい。
var saveBytes = function(bytes, filename) {
var uri, a;
if (navigator.msSaveBlob) {
navigator.msSaveBlob(new Blob([new Uint8Array(bytes)]), filename);
return;
}
if (window.URL && window.URL.createObjectURL) {
uri = URL.createObjectURL(new Blob([new Uint8Array(bytes)]));
} else {
uri = 'data:application/octet-stream;base64,' +
encodeURIComponent(btoa(String.fromCharCode.apply(null, bytes)));;
}
a = document.createElement('A');
a.href = uri;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};
saveBytes(
[137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,1,0,0,0,1,8,6,0,0,0,31,21,196,137,0,0,0,13,73,68,65,84,8,153,99,96,96,96,96,0,0,0,5,0,1,135,161,78,212,0,0,0,0,73,69,78,68,174,66,96,130],
"spacer.png"
); //1x1 PNG