Skip to content

非公式本サイトは非公式の日本語ドキュメントであり、Cloudflare 公式サイトではありません。最新情報はdevelopers.cloudflare.comをご確認ください。

Workers でホスト済み画像を管理する

最終更新 Markdown で表示Agent セットアップ

バインディング は、Worker を Developer Platform 上の外部リソース(ImagesR2 バケット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) を呼び出してハンドルを取得し、そのハンドルのメソッドを呼び出します。

.upload(image, options)

新しい画像をアカウントにアップロードします。画像バイトはストリームまたは ArrayBuffer で渡せます。ImageMetadata を返します。

次のオプションを ImageUploadOptions オブジェクトとして受け付けます。

  • id string — 画像に割り当てるカスタム ID。省略すると、Cloudflare が UUID を生成します。カスタムパスへのアップロード を参照してください。
  • filename string — 画像に関連付けるファイル名。
  • requireSignedURLs boolean — 閲覧に署名付き URL を必須にするかどうか。デフォルトは false です。
  • metadata Record<string, unknown> — 画像と一緒に保存する任意のメタデータ。
  • creator string — 画像作成者の、ユーザー定義の識別子。
  • encoding 'base64' — 渡したバイトが Base64 エンコード済みの場合は base64 を指定します。バインディングはアップロード前にデコードします。

.createDirectUpload(options)

クライアントが API トークンを見せずに直接画像をアップロードできる Direct Creator Upload URL を作成します。DirectUploadResult を返します。

次のオプションを DirectUploadOptions オブジェクトとして受け付けます。

  • id string 任意 — 画像に割り当てるカスタム ID。省略すると、Cloudflare が自動で UUID を生成します。カスタムパスへのアップロード を参照してください。
  • metadata Record<string, unknown> 任意 — アップロード後に画像と一緒に保存する任意のメタデータ。
  • requireSignedURLs boolean 任意 — アップロードした画像の閲覧に署名付き URL を必須にするかどうか。デフォルトは false です。
  • creator string 任意 — 画像作成者の、ユーザー定義の識別子。
  • expiresIn number 任意 — アップロード URL の有効期間(秒)。120 から 21600 の間である必要があります。デフォルトは 1800 です。

.list(options)

ページネーション付きで、アカウント内の画像を一覧します。ImageList を返します。

次のオプションを ImageListOptions オブジェクトとして受け付けます。

  • limit number — 1 ページで返す画像の最大数。
  • cursor string — 前回の list() 呼び出しが返した継続トークン。最初のページでは省略します。
  • sortOrder 'asc' | 'desc'uploaded タイムスタンプでの並び順。デフォルトは asc です。
  • creator string — この作成者識別子でアップロードされた画像に結果を絞り込みます。
  • filter ImageListFilter — 画像のプロパティで結果を絞り込みます。カスタムメタデータで絞り込む metadata フィールドを受け付けます。

カスタムメタデータで絞り込む

画像を一覧するとき、.list()filter.metadata を渡すと、カスタムメタデータフィールドで画像を返せます。

filter.metadata の各エントリはメタデータフィールド名で、その値がフィールドの条件になります。複数のエントリを渡した場合、画像はすべてに一致したときだけ返されます。

フィールド名に使えるのは、文字、数字、アンダースコア、ドットだけです。ハイフンやスペースなど、それ以外の文字を含むメタデータフィールド名では絞り込めません。

ネストしたフィールドで絞り込むには、ドット記法で階層を区切ります。たとえば { "config.region": "eu-west" }{ config: { region: "eu-west" } } に一致します。フィールドパスは最大 5 階層です。

次の演算子を ImageMetadataFilterOperators オブジェクトとして受け付けます。

  • eq string | number | boolean — フィールドの完全一致です。
  • in Array<string> | Array<number> — 配列内のいずれかの値にフィールドが一致します。配列は最大 10 値で、文字列値にパイプ文字(|)は使えません。
  • gt number — 値より大きいフィールドに一致します。
  • gte number — 値以上のフィールドに一致します。
  • lt number — 値より小さいフィールドに一致します。
  • lte number — 値以下のフィールドに一致します。

プレーンな値は完全一致の省略形です。そのため { 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));
	},
};

.image(imageId)

ホスト済み画像 1 件のハンドルを返します。imageId は、Cloudflare が生成した UUID または カスタム ID です。

ハンドル自体はネットワークリクエストを発行しないため、作成コストは低く抑えられます。

.image(imageId).details()

画像のメタデータを取得します。指定した ID の画像があれば ImageMetadata を、なければ null を返します。

.image(imageId).bytes()

画像の生バイトを取得します。指定した ID の画像があれば ReadableStream<Uint8Array> を、なければ null を返します。アップロードした元ファイルをストリームします。配信前に最適化するには、画像バイトを .input() に渡します。事前定義バリアントを配信するには、ImageMetadata.variants が返す URL、または 画像配信 URL を使います。

.image(imageId).update(options)

画像のメタデータまたはアクセス制御を更新します。すべてのフィールドは任意で、指定したフィールドだけが変わります。更新後の値を含む ImageMetadata を返します。

次のオプションを ImageUpdateOptions オブジェクトとして受け付けます。

  • requireSignedURLs boolean — 画像の閲覧に署名付き URL を必須にするかどうか。カスタム ID でアップロードした画像では true にできません。
  • metadata Record<string, unknown> — 画像の置き換え用メタデータ。既存メタデータにマージするのではなく、置き換えます。
  • creator string — 画像作成者の、ユーザー定義の識別子。

.image(imageId).delete()

画像を削除します。削除できた場合は true、指定した ID の画像がなかった場合は false を返します。

.image(imageId).signedUrl(options)

署名付き URL が必要な 画像向けに、署名付きの 画像配信 URL を生成します。string を返します。

署名付き URL を返すと、ブラウザーは Worker 経由でバイトをプロキシせずに、非公開画像を直接取得できます。URL は Cloudflare 側で署名されるため、Worker がアカウントの署名鍵を扱うことはありません。

次のオプションを ImageSignedUrlOptions オブジェクトとして受け付けます。

  • variant string — 配信する バリアント
  • expiresIn number 任意 — URL の有効期間(秒)。省略すると、URL は期限切れになりません。
  • keyName string 任意 — 使う 署名鍵 の名前。デフォルトは 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);
	},
};

Base64 エンコード済み画像をアップロードする

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 });
	},
};

1 件の画像の詳細を取得する

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 を生成する

短命の署名付き 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);
	},
};

Direct Creator Upload URL を作成する

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 });
	},
};

リモート画像を Images ストレージに取り込む

この例では、リモート 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],
		});
	},
};

型定義

ImageMetadata

画像の取得、作成、更新の操作が返します。

  • id string
    • 画像の一意の識別子です。
  • filename string 任意
    • アップロード時に指定した元のファイル名です。
  • uploaded string 任意
    • 画像がアップロードされた日時で、ISO 8601 文字列です。
  • requireSignedURLs boolean
    • この画像へのアクセスに署名付き URL が必要かどうか。非公開画像の配信 を参照してください。
  • meta Record<string, unknown> 任意
    • 画像に関連付けた、ユーザー指定のメタデータです。
  • variants Array<string>
    • アカウントに設定した各バリアントの完成済み URL です。バリアントの作成 を参照してください。
  • draft boolean 任意
    • 画像が下書き状態(バイト未アップロード)かどうか。下書きは、通常 Direct Creator Uploads を使うアカウントでのみ見られます。
  • creator string 任意
    • 画像作成者の、ユーザー定義の識別子です。

ImageList

list() が返します。

  • images Array<ImageMetadata>
    • このページの結果に含まれる画像です。
  • cursor string 任意
    • 次の list() 呼び出しに渡す継続トークンです。続きがある場合にだけ存在します。
  • listComplete boolean
    • 続きのページがなければ true、あれば false です。

DirectUploadResult

createDirectUpload() が返します。

  • id string
    • アップロードした画像が持つ ID です。
  • uploadURL string
    • クライアントが画像バイトをアップロードする 1 回限りの URL です。

エラー処理

失敗するメソッド(.upload().list().createDirectUpload().update().signedUrl())は、次のプロパティを持つ ImagesError を投げます。

  • code number
    • 失敗モードを識別する数値のエラーコードです。
  • message string
    • 人が読めるエラーの説明です。

1 件の画像を取得するメソッド(.details().bytes().delete())は、「見つからない」場合に例外を投げず、null または false を返します。

例外を投げうる操作は、try...catch ブロックで囲むとよいです。

ローカル開発

wrangler dev を実行すると、ホスト済み画像の管理操作は、埋め込み KV 名前空間に画像を保存するローカルモックが処理します。このモックは、このページで説明するすべてのメソッドに対応しているため、オフラインで Worker を開発およびテストできます。

モックはローカル開発専用です。ローカル環境から本番の Images サービスを使うには、wrangler dev --remote を実行します。

関連リソース

役に立ちましたか?