runlot

署名付き URL

ログインしていないユーザーでも限られた時間だけ利用できる URL を生成します。アップロードとダウンロードの両方に対応します。

const url = await env.storage.presign("covers/hello.png");

既定のリクエストメソッドは GET、有効期限は 300 秒 です。

await env.storage.presign(key, { method: "GET", ttl: 60 });    // 1 分間ダウンロード可能
await env.storage.presign(key, { method: "PUT", ttl: 3600 });  // 1 時間アップロード可能

ttl は秒単位で、最大 3,600 秒(1 時間) です。この値を超えるとリクエストを拒否します。

ブラウザから直接アップロードする構成

ワーカーは URL を発行するだけで、ファイルのデータはワーカーを経由しません。

// ワーカー
app.post("/upload-url", async (c) => {
  const { name, type } = await c.req.json();
  const key = `uploads/${crypto.randomUUID()}/${name}`;
  const url = await c.env.storage.presign(key, { method: "PUT", ttl: 600 });
  return Response.json({ key, url });
});
// ブラウザ
const { key, url } = await fetch("/upload-url", {
  method: "POST",
  body: JSON.stringify({ name: file.name, type: file.type }),
}).then((r) => r.json());

await fetch(url, { method: "PUT", body: file });

キーはワーカーで生成することが重要です。クライアントから渡されたファイル名をそのままキーに使うと、他のユーザーのファイルを上書きできてしまいます。

GET と PUT のみ対応します

DELETE リクエスト用の署名付き URL は作成できません。削除は常に、ワーカーで権限を確認したうえで実行してください。漏れた URL ひとつがファイルの削除権限になることを防ぐためです。

ストレージバックエンドによる制限

署名付き URL はオブジェクトストレージのバックエンドでのみ利用できます。ローカル開発環境のようにディスクバックエンドを使用している場合は、501 エラー(unsupported)を返します。

ローカルで署名付き URL を使う流れをテストしたい場合は、ワーカーがファイルを直接返す代替経路を用意できます。

let url: string;
try {
  url = await env.storage.presign(key, { ttl: 600 });
} catch {
  url = `/files/${encodeURIComponent(key)}`; // ワーカーが get でファイルを返す経路
}

クォータ超過時の動作

書き込み用の署名付き URL は、ストレージ容量がいっぱいになると発行されません(507)。読み取り用の URL は引き続き発行できます。ファイルを削除して容量を確保できる必要があるためです。

このページの目次