概要・成果物
普段S3をよく利用していますが、オブジェクトをまとめてダウンロードする機能がマネジメントコンソールにはなく、CLIを併用する必要があり手間に感じていました。
そこで、選択したオブジェクトを一括でダウンロードできるボタンを追加するブラウザ拡張機能を作成しました。(なぜ標準では一括でダウンロードできないのでしょうか。。?)
コード
お気持ちはコメントに書いておきました。
やっていることは至ってシンプルで以下の2種類です。
- チェックボックスが入っているオブジェクトの情報を取得
- 1個1個チェックボックスを取り外ししてダウンロードしていく
主要な処理はbulkButtonsとonClickBulkProcessの2つの関数に集約しています。
const bulkButtons = () => {
// ダウンロードボタンや開くボタンなどlist-objectsが表示されている画面で表示されるtoolbarのclassを取得
const toolbar = document.querySelector<HTMLDivElement>(
'div[data-testid="object-list-table-action-buttons"]',
);
// すでにDownloadボタンを表示しているか
const existingDownload = document.getElementById("bulk-download-btn");
// awsのダウンロードボタン
const awsDownLoadButton = document.querySelector<HTMLButtonElement>(
"#download-object-button",
);
const configs = [
{
existing: existingDownload,
awsButton: awsDownLoadButton,
id: "bulk-download-btn",
text: "一括ダウンロード",
},
];
configs.forEach(({ existing, awsButton, id, text }) => {
if (toolbar && awsButton) {
// 今現在一括ダウンロードボタンが存在していなくてtoolbar, downloadボタンがある場合はボタンを追加
if (!existing) {
const btn = document.createElement("button");
btn.id = id;
btn.textContent = text;
btn.className =
"copy-button copy-object-url-button awsui_button_vjswe_1379u_157 awsui_variant-normal_vjswe_1379u_205";
btn.style.marginLeft = "6px";
btn.addEventListener("click", () => onClickBulkProcess(awsButton));
toolbar.appendChild(btn);
}
} else if (existing) {
// 存在していないページではボタンをremove
existing.remove();
}
});
// ボタンのdisable, ableの制御
updateBulkButtonsDisabledState();
};
const onClickBulkProcess = async (button: HTMLButtonElement) => {
const allCheckboxes = getCurrentCheckBoxStatus();
const preCheckBoxStatus = allCheckboxes.map((item) => item.checked);
// 最初に1個1個チェックを外しておく
allCheckboxes.forEach((cb) => {
if (cb.checked) cb.click();
});
for (let i = 0; i < allCheckboxes.length; i++) {
if (!preCheckBoxStatus[i]) continue;
// チェックされている物を1個ずつ選択してダウンロードボタンをクリック
allCheckboxes[i].click();
button.click();
await new Promise((r) => setTimeout(r, 200));
// チェックボックスを外す
allCheckboxes[i].click();
}
// 最初の状態に戻す
for (let i = 0; i < allCheckboxes.length; i++) {
if (preCheckBoxStatus[i]) {
allCheckboxes[i].click();
}
}
};
const updateBulkButtonsDisabledState = () => {
// チェックボックスに1つ以上checkがついていたらdisableをとるようにする
const anyChecked = getCurrentCheckBoxStatus().some((cb) => cb.checked);
["bulk-download-btn"].forEach((id) => {
const btn = document.getElementById(id);
if (btn) {
btn.classList.toggle("awsui_disabled_vjswe_1379u_223", !anyChecked);
}
});
};
// 現在のチェックボックスリストを取得
const getCurrentCheckBoxStatus = (): HTMLInputElement[] =>
Array.from(
document.querySelectorAll<HTMLInputElement>(
'input[type="checkbox"][class^="awsui_native-input"]',
),
);
// 画面が変わったときにbuikButtonsを実行できるように監視
const observer = new MutationObserver(() => {
bulkButtons();
});
observer.observe(document.body, { childList: true, subtree: true });
// 初期実行
bulkButtons();
ソースコード
ソースコードは以下です。
chromeに公開しようとしたら登録で登録料に5$かかると言われたのでケチってやめました。
注意事項
DOM操作で1つずつダウンロードボタンをクリックしているだけのため、フォルダ構造の一括ダウンロードには対応していません。
最後に
個人的によくファイルをまとめて取得するため、作業効率が向上しました。
どなたかのお役に立てれば幸いです。
