🔖

Cloudflare Imagesで全IMAGE_IDを列挙とか全IMAGE削除とか

2022/09/23に公開

はじめに

Cloudflare Imagesで画像を配信するのがとっても便利ですね!
ストレージとCDNを兼ね備えているし、ログインした人だけに画像のアクセス権を付けるのとかもスムーズにできるし、必要十分な機能を兼ね備えていて、月額$6(ストレージ$5+通信$1)から使えます!
https://www.cloudflare.com/ja-jp/products/cloudflare-images/

やりたいこと

初回利用の際、試しに1400点くらいの画像を一括アップロードしちゃって、
さすがに適当にやりすぎたので、一度全削除したくなりました。
でもWebコンソールでは1ページ30点ずつしか表示されなくて、
30点ずつポチポチ操作するのはひじょーに面倒くさい。

幸いAPIが色々と用意されているので、APIで一括削除する方法をメモしておきます。

やり方

「イメージID一覧を取得して、IDを元にイメージを削除していく」
というのをすればOKです。

APIトークンは、この画面から作成。
アカウントIDも右端で確認可能(キャプチャではボカシ入れてます)

イメージIDを一括取得

100件ずつしか取れないのでループします。
言語は何でもいいんですけど、ここではNode.js+axiosを使って実行。

list-images.js
const axios = require('axios')

const main = async () => {
  try {
    const imageIds = []
    for (let i = 1; true; i++) {
      const { data } = await axios(
        `https://api.cloudflare.com/client/v4/accounts/${process.env.ACCOUNT_ID}/images/v1?page=${i}&per_page=100`,
        {
          method: 'GET',
          headers: { Authorization: `Bearer ${process.env.API_TOKEN}` },
        }
      )

      const length = data.result.images.length
      if (length === 0) {
        break
      }
      console.error(`${i}, ${length}`)
      imageIds.push(data.result.images.map((_) => _.id))
    }
    console.error('total: ', imageIds.flat().length)
    console.log(JSON.stringify(imageIds, null, 2))
  } catch (e) {
    console.error(e)
  }
}

main()

進捗状況はconsole.errorで、結果はconsole.logで出してるので、
リダイレクトすると、進捗状況だけが画面表示されて便利ですよ。

$ node list-images.js > image-ids.json
1, 100
2, 100
3, 100
4, 100
5, 100
6, 100
7, 100
8, 100
9, 100
10, 100
11, 100
12, 100
13, 100
14, 96
total:  1396

全イメージを削除

一括取得した結果のJSONファイル(イメージIDの配列)を再度読み込んで、それを元に一括削除します。
JSONファイル内は100件単位でグループ化された二次元配列になってるので、
その構造のまま2重ループをかけて、100件単位でPromise.allで並列処理します。

※1400件すべてを並列処理しようとすると、途中で「429 Too Many Requests」で叱られるので注意。

delete-images.js
const axios = require('axios')
const imageIdsGroups = require('./image-ids.json')

const main = async () => {
  try {
    let total = 0
    for (const imageIds of imageIdsGroups) {
      const promises = []
      for (const imageId of imageIds) {
        promises.push(
          axios(`https://api.cloudflare.com/client/v4/accounts/${process.env.ACCOUNT_ID}/images/v1/${imageId}`, {
            method: 'DELETE',
            headers: { Authorization: `Bearer ${process.env.API_TOKEN}` },
          })
        )
      }
      await Promise.all(promises)
      console.error(`${(total += imageIds.length)} / ${imageIdsGroups.flat().length}`)
    }
  } catch (e) {
    console.error(e)
  }
}

main()
$ node delete-images.js
100 / 1396
200 / 1396
300 / 1396
400 / 1396
500 / 1396
600 / 1396
700 / 1396
800 / 1396
900 / 1396
1000 / 1396
1100 / 1396
1200 / 1396
1300 / 1396
1396 / 1396

Discussion