バインディング は、Worker を Developer Platform 上の外部リソース(Images、R2 バケット、KV 名前空間 など)に接続します。
ホスト済み画像を管理するとき、Images バインディングを使うと、REST API を直接呼び出さずに、Worker からホスト済み画像のアップロード、一覧取得、取得、更新、削除ができます。hosted 名前空間は、保存と管理の操作を公開します。このバインディングは、ホスト済み画像の最適化 にも使えます。
バインディングは、Worker の Cloudflare ダッシュボード、またはプロジェクトディレクトリの Wrangler 設定ファイルで構成できます。
Images を Worker にバインドするには、Wrangler 設定ファイルに次を追加します。
{
"images": {
"binding": "IMAGES", // available in your Worker on env.IMAGES
},
}[images]
binding = "IMAGES"Worker コード内では、env.IMAGES.hosted 名前空間を使ってホスト済み画像を管理できます。
env.IMAGES.hosted 名前空間では、アカウント全体の画像をアップロードおよび一覧取得できます。特定の画像を管理するには、.image(imageId) を呼び出してハンドルを取得し、そのハンドルのメソッドを呼び出します。
新しい画像をアカウントにアップロードします。画像バイトはストリームまたは ArrayBuffer で渡せます。ImageMetadata を返します。
次のオプションを ImageUploadOptions オブジェクトとして受け付けます。
idstring— 画像に割り当てるカスタム ID。省略すると、Cloudflare が UUID を生成します。カスタムパスへのアップロード を参照してください。filenamestring— 画像に関連付けるファイル名。requireSignedURLsboolean— 閲覧に署名付き URL を必須にするかどうか。デフォルトはfalseです。metadataRecord<string, unknown>— 画像と一緒に保存する任意のメタデータ。creatorstring— 画像作成者の、ユーザー定義の識別子。encoding'base64'— 渡したバイトが Base64 エンコード済みの場合はbase64を指定します。バインディングはアップロード前にデコードします。
クライアントが API トークンを見せずに直接画像をアップロードできる Direct Creator Upload URL を作成します。DirectUploadResult を返します。
次のオプションを DirectUploadOptions オブジェクトとして受け付けます。
idstring任意 — 画像に割り当てるカスタム ID。省略すると、Cloudflare が自動で UUID を生成します。カスタムパスへのアップロード を参照してください。metadataRecord<string, unknown>任意 — アップロード後に画像と一緒に保存する任意のメタデータ。requireSignedURLsboolean任意 — アップロードした画像の閲覧に署名付き URL を必須にするかどうか。デフォルトはfalseです。creatorstring任意 — 画像作成者の、ユーザー定義の識別子。expiresInnumber任意 — アップロード URL の有効期間(秒)。120から21600の間である必要があります。デフォルトは1800です。
ページネーション付きで、アカウント内の画像を一覧します。ImageList を返します。
次のオプションを ImageListOptions オブジェクトとして受け付けます。
limitnumber— 1 ページで返す画像の最大数。cursorstring— 前回のlist()呼び出しが返した継続トークン。最初のページでは省略します。sortOrder'asc' | 'desc'—uploadedタイムスタンプでの並び順。デフォルトはascです。creatorstring— この作成者識別子でアップロードされた画像に結果を絞り込みます。filterImageListFilter— 画像のプロパティで結果を絞り込みます。カスタムメタデータで絞り込むmetadataフィールドを受け付けます。
画像を一覧するとき、.list() に filter.metadata を渡すと、カスタムメタデータフィールドで画像を返せます。
filter.metadata の各エントリはメタデータフィールド名で、その値がフィールドの条件になります。複数のエントリを渡した場合、画像はすべてに一致したときだけ返されます。
フィールド名に使えるのは、文字、数字、アンダースコア、ドットだけです。ハイフンやスペースなど、それ以外の文字を含むメタデータフィールド名では絞り込めません。
ネストしたフィールドで絞り込むには、ドット記法で階層を区切ります。たとえば { "config.region": "eu-west" } は { config: { region: "eu-west" } } に一致します。フィールドパスは最大 5 階層です。
次の演算子を ImageMetadataFilterOperators オブジェクトとして受け付けます。
eqstring | number | boolean— フィールドの完全一致です。inArray<string> | Array<number>— 配列内のいずれかの値にフィールドが一致します。配列は最大 10 値で、文字列値にパイプ文字(|)は使えません。gtnumber— 値より大きいフィールドに一致します。gtenumber— 値以上のフィールドに一致します。ltnumber— 値より小さいフィールドに一致します。ltenumber— 値以下のフィールドに一致します。
プレーンな値は完全一致の省略形です。そのため { status: "active" } は { status: { eq: "active" } } と同じです。
1 つのエントリに複数の条件がある場合、画像はすべての条件に一致したときだけ返されます。範囲に一致させるには、同じエントリで 2 つの演算子を組み合わせます。たとえば { priority: { gte: 2, lte: 5 } } は、priority が 2 から 5 の画像を返します。
1 回の呼び出しで受け付ける条件は最大 5 個です。演算子 1 つが条件 1 つとして数えられるため、{ priority: { gte: 2, lte: 5 } } のような上下限付きの範囲は 2 つ使います。
未対応のフィールド名を参照する、未対応の演算子を使う、または条件が 5 つを超えるリクエストは、絞り込みなしの結果を返すのではなく失敗します。
export default {
async fetch(request, env) {
const { images } = await env.IMAGES.hosted.list({
filter: {
metadata: {
status: "active",
priority: { gte: 2, lte: 5 },
},
},
});
return Response.json(images.map((image) => image.id));
},
};export default {
async fetch(request, env) {
const { images } = await env.IMAGES.hosted.list({
filter: {
metadata: {
status: "active",
priority: { gte: 2, lte: 5 },
},
},
});
return Response.json(images.map((image) => image.id));
},
};ホスト済み画像 1 件のハンドルを返します。imageId は、Cloudflare が生成した UUID または カスタム ID です。
ハンドル自体はネットワークリクエストを発行しないため、作成コストは低く抑えられます。
画像のメタデータを取得します。指定した ID の画像があれば ImageMetadata を、なければ null を返します。
画像の生バイトを取得します。指定した ID の画像があれば ReadableStream<Uint8Array> を、なければ null を返します。アップロードした元ファイルをストリームします。配信前に最適化するには、画像バイトを .input() に渡します。事前定義バリアントを配信するには、ImageMetadata.variants が返す URL、または 画像配信 URL を使います。
画像のメタデータまたはアクセス制御を更新します。すべてのフィールドは任意で、指定したフィールドだけが変わります。更新後の値を含む ImageMetadata を返します。
次のオプションを ImageUpdateOptions オブジェクトとして受け付けます。
requireSignedURLsboolean— 画像の閲覧に署名付き URL を必須にするかどうか。カスタム ID でアップロードした画像ではtrueにできません。metadataRecord<string, unknown>— 画像の置き換え用メタデータ。既存メタデータにマージするのではなく、置き換えます。creatorstring— 画像作成者の、ユーザー定義の識別子。
画像を削除します。削除できた場合は true、指定した ID の画像がなかった場合は false を返します。
署名付き URL が必要な 画像向けに、署名付きの 画像配信 URL を生成します。string を返します。
署名付き URL を返すと、ブラウザーは Worker 経由でバイトをプロキシせずに、非公開画像を直接取得できます。URL は Cloudflare 側で署名されるため、Worker がアカウントの署名鍵を扱うことはありません。
次のオプションを ImageSignedUrlOptions オブジェクトとして受け付けます。
variantstring— 配信する バリアント。expiresInnumber任意 — URL の有効期間(秒)。省略すると、URL は期限切れになりません。keyNamestring任意 — 使う 署名鍵 の名前。デフォルトはdefaultです。
export default {
async fetch(request, env) {
if (!request.body) {
return new Response("Missing body", { status: 400 });
}
const image = await env.IMAGES.hosted.upload(request.body, {
filename: "upload.jpg",
metadata: { source: "worker" },
requireSignedURLs: false,
});
return Response.json(image);
},
};export default {
async fetch(request, env) {
if (!request.body) {
return new Response("Missing body", { status: 400 });
}
const image = await env.IMAGES.hosted.upload(request.body, {
filename: "upload.jpg",
metadata: { source: "worker" },
requireSignedURLs: false,
});
return Response.json(image);
},
};encoding: "base64" を指定すると、バインディングがアップロード前に本文をデコードします。
export default {
async fetch(request, env) {
if (!request.body) {
return new Response("Missing body", { status: 400 });
}
const image = await env.IMAGES.hosted.upload(request.body, {
encoding: "base64",
filename: "upload.png",
});
return Response.json(image);
},
};export default {
async fetch(request, env) {
if (!request.body) {
return new Response("Missing body", { status: 400 });
}
const image = await env.IMAGES.hosted.upload(request.body, {
encoding: "base64",
filename: "upload.png",
});
return Response.json(image);
},
};export default {
async fetch(request, env) {
let cursor;
const ids = [];
do {
const page = await env.IMAGES.hosted.list({ limit: 100, cursor });
ids.push(...page.images.map((image) => image.id));
cursor = page.cursor;
} while (cursor);
return Response.json({ count: ids.length, ids });
},
};export default {
async fetch(request, env) {
let cursor: string | undefined;
const ids: string[] = [];
do {
const page = await env.IMAGES.hosted.list({ limit: 100, cursor });
ids.push(...page.images.map((image) => image.id));
cursor = page.cursor;
} while (cursor);
return Response.json({ count: ids.length, ids });
},
};export default {
async fetch(request, env) {
const details = await env.IMAGES.hosted.image("IMAGE_ID").details();
if (!details) {
return new Response("Not found", { status: 404 });
}
return Response.json(details);
},
};export default {
async fetch(request, env) {
const details = await env.IMAGES.hosted.image("IMAGE_ID").details();
if (!details) {
return new Response("Not found", { status: 404 });
}
return Response.json(details);
},
};export default {
async fetch(request, env) {
const bytes = await env.IMAGES.hosted.image("IMAGE_ID").bytes();
if (!bytes) {
return new Response("Not found", { status: 404 });
}
return new Response(bytes);
},
};export default {
async fetch(request, env) {
const bytes = await env.IMAGES.hosted.image("IMAGE_ID").bytes();
if (!bytes) {
return new Response("Not found", { status: 404 });
}
return new Response(bytes);
},
};export default {
async fetch(request, env) {
const updated = await env.IMAGES.hosted.image("IMAGE_ID").update({
metadata: { reviewed: true },
});
return Response.json(updated);
},
};export default {
async fetch(request, env) {
const updated = await env.IMAGES.hosted.image("IMAGE_ID").update({
metadata: { reviewed: true },
});
return Response.json(updated);
},
};export default {
async fetch(request, env) {
const deleted = await env.IMAGES.hosted.image("IMAGE_ID").delete();
return new Response(deleted ? "Deleted" : "Not found", {
status: deleted ? 200 : 404,
});
},
};export default {
async fetch(request, env) {
const deleted = await env.IMAGES.hosted.image("IMAGE_ID").delete();
return new Response(deleted ? "Deleted" : "Not found", {
status: deleted ? 200 : 404,
});
},
};短命の署名付き URL にブラウザーをリダイレクトし、Worker 経由でバイトをストリームせずに非公開画像を直接取得させます。
export default {
async fetch(request, env) {
const url = await env.IMAGES.hosted.image("IMAGE_ID").signedUrl({
variant: "private",
expiresIn: 86_400,
});
return Response.redirect(url, 302);
},
};export default {
async fetch(request, env) {
const url = await env.IMAGES.hosted.image("IMAGE_ID").signedUrl({
variant: "private",
expiresIn: 86_400,
});
return Response.redirect(url, 302);
},
};1 回限りのアップロード URL を作成してクライアントに返します。クライアントは、Worker がバイトや API トークンを扱わずに、Cloudflare へ直接画像をアップロードできます。
export default {
async fetch(request, env) {
const { id, uploadURL } = await env.IMAGES.hosted.createDirectUpload({
metadata: { userId: "abc123" },
requireSignedURLs: true,
expiresIn: 600,
});
return Response.json({ id, uploadURL });
},
};export default {
async fetch(request, env) {
const { id, uploadURL } = await env.IMAGES.hosted.createDirectUpload({
metadata: { userId: "abc123" },
requireSignedURLs: true,
expiresIn: 600,
});
return Response.json({ id, uploadURL });
},
};この例では、リモート URL から画像を取得し、Images アカウントにアップロードして、最初のバリアント URL を返します。
export default {
async fetch(request, env) {
const upstream = await fetch("https://example.com/photo.jpg");
if (!upstream.ok || !upstream.body) {
return new Response("Upstream fetch failed", { status: 502 });
}
const image = await env.IMAGES.hosted.upload(upstream.body, {
filename: "photo.jpg",
metadata: { source: "example.com" },
});
return Response.json({
id: image.id,
variant: image.variants[0],
});
},
};export default {
async fetch(request, env) {
const upstream = await fetch("https://example.com/photo.jpg");
if (!upstream.ok || !upstream.body) {
return new Response("Upstream fetch failed", { status: 502 });
}
const image = await env.IMAGES.hosted.upload(upstream.body, {
filename: "photo.jpg",
metadata: { source: "example.com" },
});
return Response.json({
id: image.id,
variant: image.variants[0],
});
},
};画像の取得、作成、更新の操作が返します。
idstring- 画像の一意の識別子です。
filenamestring任意- アップロード時に指定した元のファイル名です。
uploadedstring任意- 画像がアップロードされた日時で、ISO 8601 文字列です。
requireSignedURLsboolean- この画像へのアクセスに署名付き URL が必要かどうか。非公開画像の配信 を参照してください。
metaRecord<string, unknown>任意- 画像に関連付けた、ユーザー指定のメタデータです。
variantsArray<string>- アカウントに設定した各バリアントの完成済み URL です。バリアントの作成 を参照してください。
draftboolean任意- 画像が下書き状態(バイト未アップロード)かどうか。下書きは、通常 Direct Creator Uploads を使うアカウントでのみ見られます。
creatorstring任意- 画像作成者の、ユーザー定義の識別子です。
list() が返します。
imagesArray<ImageMetadata>- このページの結果に含まれる画像です。
cursorstring任意- 次の
list()呼び出しに渡す継続トークンです。続きがある場合にだけ存在します。
- 次の
listCompleteboolean- 続きのページがなければ
true、あればfalseです。
- 続きのページがなければ
createDirectUpload() が返します。
idstring- アップロードした画像が持つ ID です。
uploadURLstring- クライアントが画像バイトをアップロードする 1 回限りの URL です。
失敗するメソッド(.upload()、.list()、.createDirectUpload()、.update()、.signedUrl())は、次のプロパティを持つ ImagesError を投げます。
codenumber- 失敗モードを識別する数値のエラーコードです。
messagestring- 人が読めるエラーの説明です。
1 件の画像を取得するメソッド(.details()、.bytes()、.delete())は、「見つからない」場合に例外を投げず、null または false を返します。
例外を投げうる操作は、try...catch ブロックで囲むとよいです。
wrangler dev を実行すると、ホスト済み画像の管理操作は、埋め込み KV 名前空間に画像を保存するローカルモックが処理します。このモックは、このページで説明するすべてのメソッドに対応しているため、オフラインで Worker を開発およびテストできます。
モックはローカル開発専用です。ローカル環境から本番の Images サービスを使うには、wrangler dev --remote を実行します。
- Workers で最適化する — バインディングを使って、Worker から画像を最適化します。
- REST API でアップロードする — 同等の HTTP API です。
- ホスト済み画像を管理する — 保存済み画像を管理するダッシュボードと API のワークフローです。