はじめに
やりたいこと
サムネイル表示されている画像ファイルをZIPにまとめてダウンロードする。
制限事項
たとえChrome拡張機能がダウンロードしたものでも、ローカルのファイルにはアクセスできない。
ゆえに、メモリ上の画像データからZIPデータを作成し、それをダウンロードする。ZIPの作成にはJSZipを使用した。
手順1:画像ファイルのパスを探す
サムネイルからリンクをたどってオリジナル画像のURLを取得する。
その際、画像ファイルが置かれているドメインを確認し、manifest.jsonのpermissions
に追加する。(Flickrの場合は、「https://c1.staticflickr.com/
」など。)ワイルドカードが使えないので、連番が降られている場合はすべての番号を追加する必要がある。
手順2:画像ファイルのダウンロード
XMLHttpRequestのresponseType
にarraybuffer
を指定することで、画像ファイルをバイナリデータとして取得できる。
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データが作成される。
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を破棄し、バイナリデータを開放する。
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);
}