Edited at

Chrome拡張機能:複数ファイルをZIPにまとめてダウンロードする

More than 1 year has passed since last update.


はじめに


やりたいこと

サムネイル表示されている画像ファイルをZIPにまとめてダウンロードする。


制限事項

たとえChrome拡張機能がダウンロードしたものでも、ローカルのファイルにはアクセスできない。

ゆえに、メモリ上の画像データからZIPデータを作成し、それをダウンロードする。ZIPの作成にはJSZipを使用した。


手順1:画像ファイルのパスを探す

サムネイルからリンクをたどってオリジナル画像のURLを取得する。

その際、画像ファイルが置かれているドメインを確認し、manifest.jsonのpermissionsに追加する。(Flickrの場合は、「https://c1.staticflickr.com/」など。)ワイルドカードが使えないので、連番が降られている場合はすべての番号を追加する必要がある。


手順2:画像ファイルのダウンロード

XMLHttpRequestのresponseTypearraybufferを指定することで、画像ファイルをバイナリデータとして取得できる。


background.js

const DownloadArraybuffer = (url) => {

const p = new Promise(resolve => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'arraybuffer';
xhr.addEventListener('loadend', () => {resolve(xhr.response);});
xhr.send();
});

return p;
}



手順3:ZIPデータを作成する

JSZipオブジェクトを作成し、fileメソッドでダウンロードした画像データを追加する。最後にgenerateAsyncメソッドを実行すればZIPデータが作成される。


background.js

const ZipGenerateAsync = (zip) => {

return new Promise((resolve, reject) => {
zip.generateAsync({type: "blob"}).then(resolve);
});
};

const CreateZipBlob = async (urlList) => {
const zip = new JSZip();

for(let i = 0; i < urlList.length; i++) {
const imageFile = await DownloadArraybuffer(urlList[i]);
const fileName = i + '.jpg'

zip.file(fileName, imageFile, {binary: true});
}

return await ZipGenerateAsync(zip);
}



手順4:ZIPデータをダウンロードする

createObjectURLの引数にバイナリデータを渡すと、ダウンロードするためのURLを発行できる。ダウンロード後はrevokeObjectURLでURLを破棄し、バイナリデータを開放する。


background.js

const DownloadFile = (url, filename) => {

return new Promise(resolve => {
chrome.downloads.download({url: url, filename: filename}, downloadId => {
resolve(downloadId);
});
});
};

const Download = async () => {
...
const zipBlob = await CreateZipBlob(urlList);
const zipUrl = window.URL.createObjectURL(blob);
const zipName = 'aaa.zip'

await DownloadFile(zipUrl, zipName);
window.URL.revokeObjectURL(zipUrl);
}