🧊

Cloudflare WorkersのKVに、圧縮済のファイルをアップロードする

たとえばウェブフォントの`woff2`とか、独自の圧縮方式を採用してるファイルとか。

そういうのをKVに入れたい場合にどうするかというメモです。

KVにファイルをアップロードする方法

色々やり方があるけど、一番お手軽だと思われるのは、`wrangler`CLIでやる方法。

wrangler kv:key put --binding=MY_KV "my-key" path/to/file --path

次に思いつくのは、RESTのAPIを使う方法。
言ってしまうと`wrangler`も内部的にはこのAPIを叩いてるので、一緒といえば一緒。

curl -X PUT \
     "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/storage/kv/namespaces/$KV_NAMESPACE/values/$KEY" \
     -H "authorization: Bearer $ACCESS_TOKEN" \
     --data-binary "@path/to/file"

RESTのAPIということは、同様のことをNodeからやれる。

const fs = require("fs");
const { fetch } = require("undici");

/**
 * @param {string} key
 * @param {string} pathToFile
 */
const putKvFile = (key, pathToFile) => fetch(
  `https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/storage/kv/namespaces/${KV_NAMESPACE}/values/${key}`,
  {
    method: "PUT",
    headers: {
      "authorization": "Bearer " + ACCESS_TOKEN,
    },
    body: fs.createReadStream(pathToFile),
  }
);

このAPIにはレート制限があって、5分の枠で1200リクエストまでとのこと。

The Cloudflare API sets a maximum of 1,200 requests in a five minute period.
https://api.cloudflare.com/#getting-started-requests

ハマったこと

  • `wrangler@beta`ではうまく動かない
    • `wrangler`CLIは、Rustで書かれた現行verと、`wrangler@beta`から利用できるTypeScriptの次期verがある
    • 先述の`-p / --path`でファイルをアップロードする方法の実装が変わったのか、次期verではうまくアップロードできなかった
    • アップロード自体は成功と表示されるけど、ファイルが壊れるみたいな感じ
    • (まだベータなせいであり、そのうち修正されると信じたい)
  • 管理画面のGUIからはアップロードできない
    • 管理画面から入力できるのは文字列だけ
  • 複数ファイルをまとめてアップロードすることはできない(という結論)

アップロードしたいのが単なる文字列であれば、何もハマることはないと思う・・。

おまけ: Workerからレスポンスするとき

const file = await MY_KV.get(key, { type: "arrayBuffer" });
return new Response(file, {
  headers: { /* ... */ }
});

`arrayBuffer`にして取り出すのがポイント。