はじめに

JavaScript で画像をローカルにダウンロードする方法を整理した。

img タグで表示されている画像を JS 実行で保存するような処理を想定。

参考: zip にまとめてダウンロード編: JavaScript で複数画像を zip に圧縮してローカルにダウンロード

TL;DR

目次

  1. はじめに
  2. TL;DR
  3. 環境・条件
  4. 詳細
    1. 完成形
    2. 解説
      1. ボタン追加: addImageDownloadButton
      2. 画像リクエスト: downloadImage
      3. 画像保存: downloadImageToLocal
    3. 参考: axios を使う場合
  5. まとめ
  6. 参考文献

環境・条件

Google Chrome バージョン: 79.0.3945.88(Official Build) (64 ビット)

詳細

いらすとや トップページのロゴ画像をダウンロード」を例にダウンロードボタンを作る。

完成形

先に完成形。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// ダウンロードボタンを追加
function addImageDownloadButton() {
document.body.insertAdjacentHTML(
"afterBegin",
`<button id="download">ロゴ画像ダウンロード</button>`
);
document.getElementById("download").addEventListener("click", downloadImage);
}

// ダウンロード処理(イベントハンドラ)
function downloadImage() {
const src = document.querySelector("#top img").getAttribute("src");

let xhr = new XMLHttpRequest();
xhr.open('GET', src, true);
xhr.responseType = "blob";
xhr.onload = downloadImageToLocal;
xhr.send();
}

// ローカルへのダウンロード処理(画像リクエスト完了時に動作)
function downloadImageToLocal() {
let dlLink = document.createElement("a");

const dataUrl = URL.createObjectURL(this.response);
dlLink.href = dataUrl;

const fileName = `いらすとやロゴ.${this.response.type.replace("image/", "")}`;
dlLink.download = fileName;

document.body.insertAdjacentElement("beforeEnd", dlLink);
dlLink.click();
dlLink.remove();

setTimeout(function() {
window.URL.revokeObjectURL(dataUrl);
}, 1000);
}

addImageDownloadButton();

上記スクリプトを Dev tools のコンソールで実行すると、トップにボタンが配置される。

このボタンをクリックすると、 いらすとやロゴ.png がダウンロードされるはず。

解説

関数単位で簡単に解説。

ボタン追加: addImageDownloadButton

1
2
3
4
5
6
7
8
// ダウンロードボタンを追加
function addImageDownloadButton() {
document.body.insertAdjacentHTML(
"afterBegin",
`<button id="download">ロゴ画像ダウンロード</button>`
);
document.getElementById("download").addEventListener("click", downloadImage);
}
  • insertAdjacentHTML でボタンを追加
  • 追加したボタンにイベントリスナを設定

画像リクエスト: downloadImage

1
2
3
4
5
6
7
8
9
10
// ダウンロード処理(イベントハンドラ)
function downloadImage() {
const src = document.querySelector("#top img").getAttribute("src");

let xhr = new XMLHttpRequest();
xhr.open('GET', src, true);
xhr.responseType = "blob";
xhr.onload = downloadImageToLocal;
xhr.send();
}

画像保存: downloadImageToLocal

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// ローカルへのダウンロード処理(画像リクエスト完了時に動作)
function downloadImageToLocal() {
let dlLink = document.createElement("a");

const dataUrl = URL.createObjectURL(this.response);
dlLink.href = dataUrl;

const fileName = `いらすとやロゴ.${this.response.type.replace("image/", "")}`;
dlLink.download = fileName;

document.body.insertAdjacentElement("beforeEnd", dlLink);
dlLink.click();
dlLink.remove();

setTimeout(function() {
window.URL.revokeObjectURL(dataUrl);
}, 1000);
}

参考: axios を使う場合

axios を使って blob でレスポンスを受け取るには、第2引数に { responseType: "blob" } を指定すれば良い。
参考: Request config - axios

※1: Dev tools に貼り付けて確認はできないので注意。
※2: Console Importer - Chrome ウェブストア をインストールすると、$i("axios") で Dev tools 上でも axios が使えるようになる。

XMLHttpRequest を使った場合。(前述のコードと同じ)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function downloadImage() {
const src = document.querySelector("#top img").getAttribute("src");

let xhr = new XMLHttpRequest();
xhr.open('GET', src, true);
xhr.responseType = "blob";
xhr.onload = downloadImageToLocal;
xhr.send();
}

function downloadImageToLocal() {
let dlLink = document.createElement("a");

const dataUrl = URL.createObjectURL(this.response);
dlLink.href = dataUrl;

const fileName = `いらすとやロゴ.${this.response.type.replace("image/", "")}`;
dlLink.download = fileName;

document.body.insertAdjacentElement("beforeEnd", dlLink);
dlLink.click();
dlLink.remove();

setTimeout(function() {
window.URL.revokeObjectURL(dataUrl);
}, 1000);
}

axios を使った場合、downloadImage が少しスッキリする。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
async function downloadImage() {
const src = document.querySelector("#top img").getAttribute("src");

// ちゃんと例外処理したほうが良いけど省略
const response = await axios.get(src, { responseType: "blob" });
downloadImageToLocal(response);
}

function downloadImageToLocal(response) {
let dlLink = document.createElement("a");

// response.data にデータ実体
const dataUrl = URL.createObjectURL(response.data);
dlLink.href = dataUrl;

const fileName = `いらすとやロゴ.${response.data.type.replace("image/", "")}`;
dlLink.download = fileName;

document.body.insertAdjacentElement("beforeEnd", dlLink);
dlLink.click();
dlLink.remove();

setTimeout(function() {
window.URL.revokeObjectURL(dataUrl);
}, 1000);
}

まとめ

参考文献

関連記事