LoginSignup
26
22

More than 5 years have passed since last update.

msSaveBlob,Data URI SchemeおよびURL.createObjectURLによるデータ保存

Posted at

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

利用できるのは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://...)では動作しない

切り替えて利用する

  1. msSaveBlobが利用可能なら使う
  2. 不可の場合、URL.createObjectURL()を利用可能ならば使う
  3. どちらも不可の場合はData URI Schemeを利用する
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
26
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
22