Help us understand the problem. What is going on with this article?

JavaScriptで画像をダウンロードしたい

JSで画像をダウンロードするのに色々調べたので備忘録です。
間違った点などあればご教授いただければ幸いです。

尚、こちらはChrome、Firefox、IE11で動作確認してます。
※Safariについては未検証です。

download属性を使えばできるらしい

下記のように、aタグにdownload属性を付与して記述すれば
ファイルをダウンロードさせることが出来ます。

<a href="/path/img/file.png" download="file.png">Image Download</a>

これだけで、画像がダウンロードできるようになります。

めっちゃ簡単。

ブラウザの対応

しかし、download属性のブラウザ実装状況 を見ると、、、

Internet Explorer : なし

でた。IE。
本当に嫌いです。

実際にやってみると、IEではダウンロードが実行されず
そのままページ遷移して画像が表示されてしまいました…。

どうやったらIEでも動くようになるのか

どうやら、navigatorオブジェクトに用意されている
msSaveBlob(blob, fileName) または msSaveOrOpenBlob(blob, fileName)
というメソッドを使えばいいらしいです。

※この2つの違いについては、こちら で詳しく説明されているので参考までにどうぞ。

実際にやってみると

HTML側
<a onclick="downloadImg();">画像ダウンロード</a>
JavaScript側
function downloadImg () {
    const fileName = 'file.png';
    const uri = '/path/img/file.png';

    let xhr = new XMLHttpRequest();
    xhr.open('GET', uri);
    xhr.responseType = 'blob';
    xhr.onloadend = () => {
        if (xhr.status !== 200) {
            return false;
        }
        window.navigator.msSaveOrOpenBlob(xhr.response, fileName);
    };
    xhr.send();
}

こんな感じになります。

Blobnavigator.msSaveOrOpenBlob を使ってファイルをローカルに保存するのを利用できるのは
IEだけで、分岐にも使えそうです。

(しかし、IE9以下は Blob が使えないため対応してません。)

まとめると

こんな感じになりました。

HTML側
<a id="download" href="#" onclick="downloadImg();">画像ダウンロード</a>
JavaScript側
function downloadImg () {
    const fileName = 'file.png';
    vonst uri = '/path/img/file.png';

    // IEはdownload属性が効かないので分岐
    if (window.navigator.msSaveOrOpenBlob) {
        let xhr = new XMLHttpRequest();
        xhr.open('GET', uri);
        xhr.responseType = 'blob';
        xhr.onloadend = () => {
            if (xhr.status !== 200) {
                return false;
            }
            window.navigator.msSaveOrOpenBlob(xhr.response, fileName);
        };
        xhr.send();
    } else {
        let link = document.getElementById('download');
        link.href = uri;
        link.download = fileName;
    }
}

気になったこと

new Blob(データ, ファイルタイプ); みたいにBlobオブジェクトを生成した方がいいのか
今回のように、XMLHttpRequest を使った方がいいのか
調べましたがよく分からなかったので、
詳しい方いらっしゃいましたらご教授頂けると幸いです。

参考

download属性のブラウザ実装状況
IEのためにa要素のdownload属性を代替する
IE11にはファイルをローカルに保存するJavaScriptのAPIが2種類用意されている - Qiita

kaonavi
クラウド人材管理ツール「カオナビ」の製造・販売・サポートを行い、企業の人材管理にイノベーションを起こすことを目的としている会社
https://www.kaonavi.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away