cloudflare-images
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCloudflare Images
Cloudflare Images
Status: Production Ready ✅
Last Updated: 2025-10-26
Dependencies: Cloudflare account with Images enabled
Latest Versions: Cloudflare Images API v2
状态:已就绪可用于生产环境 ✅
最后更新:2025-10-26
依赖:已启用Images服务的Cloudflare账户
最新版本:Cloudflare Images API v2
Overview
概述
Cloudflare Images provides two powerful features:
- Images API: Upload, store, and serve images with automatic optimization and variants
- Image Transformations: Resize, optimize, and transform any publicly accessible image
Key Benefits:
- Global CDN delivery
- Automatic WebP/AVIF conversion
- Variants for different use cases (up to 100)
- Direct creator upload (user uploads without API keys)
- Signed URLs for private images
- Transform any image via URL or Workers
Cloudflare Images提供两项强大功能:
- Images API:上传、存储并提供图片,支持自动优化及变体管理
- 图片转换:调整大小、优化并转换任何可公开访问的图片
核心优势:
- 全球CDN分发
- 自动WebP/AVIF格式转换
- 支持最多100种不同使用场景的图片变体
- 直接创作者上传(用户无需API密钥即可上传)
- 签名URL用于私有图片访问
- 通过URL或Workers实现图片转换
Quick Start (5 Minutes)
快速入门(5分钟)
1. Enable Cloudflare Images
1. 启用Cloudflare Images
Log into Cloudflare dashboard → Images → Enable for your account.
Get your Account ID and create an API token with Cloudflare Images: Edit permissions.
Why this matters:
- Account ID and API token are required for all API operations
- Images Free plan includes limited transformations
登录Cloudflare控制台 → Images → 为您的账户启用该服务。
获取您的账户ID,并创建一个拥有Cloudflare Images: Edit权限的API令牌。
重要性:
- 所有API操作都需要账户ID和API令牌
- Images免费套餐包含有限的转换次数
2. Upload Your First Image
2. 上传您的第一张图片
bash
curl --request POST \
--url https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/images/v1 \
--header 'Authorization: Bearer <API_TOKEN>' \
--header 'Content-Type: multipart/form-data' \
--form 'file=@./image.jpg'Response includes:
- : Image ID for serving
id - : Array of delivery URLs
variants
CRITICAL:
- Use encoding (NOT
multipart/form-data)application/json - Image ID is automatically generated (or use custom ID)
bash
curl --request POST \
--url https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/images/v1 \
--header 'Authorization: Bearer <API_TOKEN>' \
--header 'Content-Type: multipart/form-data' \
--form 'file=@./image.jpg'响应内容包括:
- : 用于访问图片的图片ID
id - : 分发URL数组
variants
关键注意事项:
- 使用编码(而非
multipart/form-data)application/json - 图片ID会自动生成(也可使用自定义ID)
3. Serve the Image
3. 访问图片
html
<img src="https://imagedelivery.net/<ACCOUNT_HASH>/<IMAGE_ID>/public" />Default variant serves the image. Replace with your own variant names.
publichtml
<img src="https://imagedelivery.net/<ACCOUNT_HASH>/<IMAGE_ID>/public" />默认的变体用于提供图片。您可以替换为自定义的变体名称。
public4. Enable Image Transformations
4. 启用图片转换
Dashboard → Images → Transformations → Select your zone → Enable for zone
Now you can transform ANY image:
html
<img src="/cdn-cgi/image/width=800,quality=85/uploads/photo.jpg" />Why this matters:
- Works on images stored OUTSIDE Cloudflare Images
- Automatic caching on Cloudflare's global network
- No additional storage costs
控制台 → Images → Transformations → 选择您的区域 → 为区域启用
现在您可以转换任意图片:
html
<img src="/cdn-cgi/image/width=800,quality=85/uploads/photo.jpg" />重要性:
- 该功能适用于未存储在Cloudflare Images中的图片
- 会在Cloudflare全球网络自动缓存
- 无额外存储成本
5. Transform via Workers (Advanced)
5. 通过Workers进行转换(进阶)
typescript
export default {
async fetch(request: Request): Promise<Response> {
const imageURL = "https://example.com/image.jpg";
return fetch(imageURL, {
cf: {
image: {
width: 800,
quality: 85,
format: "auto" // WebP/AVIF for supporting browsers
}
}
});
}
};typescript
export default {
async fetch(request: Request): Promise<Response> {
const imageURL = "https://example.com/image.jpg";
return fetch(imageURL, {
cf: {
image: {
width: 800,
quality: 85,
format: "auto" // 为支持的浏览器自动返回WebP/AVIF格式
}
}
});
}
};The 3-Feature System
三大功能体系
Feature 1: Images API (Upload & Storage)
功能1:Images API(上传与存储)
Store images on Cloudflare's network and serve them globally.
Upload Methods:
- File Upload - Upload files directly from your server
- Upload via URL - Ingest images from external URLs
- Direct Creator Upload - Generate one-time upload URLs for user uploads
Serving Options:
- Default domain:
imagedelivery.net - Custom domains:
/cdn-cgi/imagedelivery/... - Signed URLs: Private images with expiry tokens
See: ,
templates/upload-api-basic.tstemplates/direct-creator-upload-backend.ts将图片存储在Cloudflare网络中并全球分发。
上传方式:
- 文件上传 - 从您的服务器直接上传文件
- URL上传 - 从外部URL导入图片
- 直接创作者上传 - 生成一次性上传URL供用户直接上传
访问选项:
- 默认域名:
imagedelivery.net - 自定义域名:
/cdn-cgi/imagedelivery/... - 签名URL: 带过期令牌的私有图片访问链接
参考示例: ,
templates/upload-api-basic.tstemplates/direct-creator-upload-backend.tsFeature 2: Image Transformations
功能2:图片转换
Optimize and resize ANY image (stored in Images or external).
Two Methods:
- URL Transformations - Special URL format
- Workers Transformations - Programmatic control via fetch
Common Transformations:
- Resize:
width=800,height=600,fit=cover - Optimize:
quality=85,format=auto - Effects:
blur=10,sharpen=3 - Crop:
gravity=face,zoom=0.5
See: ,
templates/transform-via-url.tstemplates/transform-via-workers.ts优化并调整任意图片的大小(无论存储在Images中还是外部)。
两种实现方式:
- URL转换 - 特殊URL格式
- Workers转换 - 通过fetch实现程序化控制
常见转换操作:
- 调整大小:
width=800,height=600,fit=cover - 优化质量:
quality=85,format=auto - 特效处理:
blur=10,sharpen=3 - 裁剪:
gravity=face,zoom=0.5
参考示例: ,
templates/transform-via-url.tstemplates/transform-via-workers.tsFeature 3: Variants
功能3:图片变体
Predefined image sizes for different use cases.
Named Variants (up to 100):
- Create once, use everywhere
- Example: ,
thumbnail,avatarhero - Consistent transformations
Flexible Variants (dynamic):
- Enable per account
- Use transformation params in URL
- Example:
w=400,sharpen=3 - Cannot use with signed URLs
See: ,
templates/variants-management.tsreferences/variants-guide.md为不同使用场景预定义图片尺寸。
命名变体(最多100种):
- 一次性创建,全局使用
- 示例: ,
thumbnail,avatarhero - 确保转换效果一致
灵活变体(动态):
- 按账户启用
- 在URL中使用转换参数
- 示例:
w=400,sharpen=3 - 不可与签名URL配合使用
参考示例: ,
templates/variants-management.tsreferences/variants-guide.mdImages API - Upload Methods
Images API - 上传方式
Method 1: File Upload (Basic)
方式1:基础文件上传
bash
curl --request POST \
https://api.cloudflare.com/client/v4/accounts/{account_id}/images/v1 \
--header "Authorization: Bearer <API_TOKEN>" \
--header "Content-Type: multipart/form-data" \
--form 'file=@./image.jpg' \
--form 'requireSignedURLs=false' \
--form 'metadata={"key":"value"}'Key Options:
- : Image file (required)
file - : Custom ID (optional, default auto-generated)
id - :
requireSignedURLsfor private images (default:true)false - : JSON object (max 1024 bytes, not visible to end users)
metadata
Response:
json
{
"result": {
"id": "2cdc28f0-017a-49c4-9ed7-87056c83901",
"filename": "image.jpg",
"uploaded": "2022-01-31T16:39:28.458Z",
"requireSignedURLs": false,
"variants": [
"https://imagedelivery.net/Vi7wi5KSItxGFsWRG2Us6Q/2cdc28f0.../public"
]
}
}See:
templates/upload-api-basic.tsbash
curl --request POST \
https://api.cloudflare.com/client/v4/accounts/{account_id}/images/v1 \
--header "Authorization: Bearer <API_TOKEN>" \
--header "Content-Type: multipart/form-data" \
--form 'file=@./image.jpg' \
--form 'requireSignedURLs=false' \
--form 'metadata={"key":"value"}'关键选项:
- : 图片文件(必填)
file - : 自定义ID(可选,默认自动生成)
id - :
requireSignedURLs表示私有图片(默认值:true)false - : JSON对象(最大1024字节,对终端用户不可见)
metadata
响应示例:
json
{
"result": {
"id": "2cdc28f0-017a-49c4-9ed7-87056c83901",
"filename": "image.jpg",
"uploaded": "2022-01-31T16:39:28.458Z",
"requireSignedURLs": false,
"variants": [
"https://imagedelivery.net/Vi7wi5KSItxGFsWRG2Us6Q/2cdc28f0.../public"
]
}
}参考示例:
templates/upload-api-basic.tsMethod 2: Upload via URL
方式2:URL上传
Ingest images from external sources without downloading first.
bash
curl --request POST \
https://api.cloudflare.com/client/v4/accounts/{account_id}/images/v1 \
--header "Authorization: Bearer <API_TOKEN>" \
--form 'url=https://example.com/image.jpg' \
--form 'metadata={"source":"external"}'When to use:
- Migrating images from another service
- Ingesting user-provided URLs
- Backing up images from external sources
CRITICAL:
- URL must be publicly accessible or authenticated
- Supports HTTP basic auth:
https://user:password@example.com/image.jpg - Cannot use both and
filein same requesturl
See:
templates/upload-via-url.ts无需先下载,直接从外部源导入图片。
bash
curl --request POST \
https://api.cloudflare.com/client/v4/accounts/{account_id}/images/v1 \
--header "Authorization: Bearer <API_TOKEN>" \
--form 'url=https://example.com/image.jpg' \
--form 'metadata={"source":"external"}'适用场景:
- 从其他服务迁移图片
- 导入用户提供的URL图片
- 备份外部源图片
关键注意事项:
- URL必须可公开访问或已通过身份验证
- 支持HTTP基本认证:
https://user:password@example.com/image.jpg - 同一请求中不能同时使用和
file参数url
参考示例:
templates/upload-via-url.tsMethod 3: Direct Creator Upload ⭐
方式3:直接创作者上传 ⭐
Generate one-time upload URLs for users to upload directly to Cloudflare (no API key exposure).
Backend Endpoint (generate upload URL):
typescript
const response = await fetch(
`https://api.cloudflare.com/client/v4/accounts/${accountId}/images/v2/direct_upload`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${apiToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
requireSignedURLs: true,
metadata: { userId: '12345' },
expiry: '2025-10-26T18:00:00Z' // Optional: default 30min, max 6hr
})
}
);
const { uploadURL, id } = await response.json();
// Return uploadURL to frontendFrontend Upload (HTML + JavaScript):
html
<form id="upload-form">
<input type="file" id="file-input" accept="image/*" />
<button type="submit">Upload</button>
</form>
<script>
document.getElementById('upload-form').addEventListener('submit', async (e) => {
e.preventDefault();
const fileInput = document.getElementById('file-input');
const formData = new FormData();
formData.append('file', fileInput.files[0]); // MUST be named 'file'
const uploadURL = 'UPLOAD_URL_FROM_BACKEND'; // Get from backend
const response = await fetch(uploadURL, {
method: 'POST',
body: formData // NO Content-Type header, browser sets multipart/form-data
});
if (response.ok) {
console.log('Upload successful!');
}
});
</script>Why this matters:
- No API key exposure to browser
- Users upload directly to Cloudflare (faster, no intermediary server)
- One-time URL expires after use or timeout
- Webhooks available for upload success/failure notifications
CRITICAL CORS FIX:
- ✅ DO: Use encoding (let browser set header)
multipart/form-data - ✅ DO: Name field (NOT
fileor other names)image - ✅ DO: Call API from backend only
/direct_upload - ❌ DON'T: Set or
Content-Type: application/jsonimage/jpeg - ❌ DON'T: Call from browser (CORS will fail)
/direct_upload
See: , ,
templates/direct-creator-upload-backend.tstemplates/direct-creator-upload-frontend.htmlreferences/direct-upload-complete-workflow.md生成一次性上传URL,用户可直接上传至Cloudflare(无需暴露API密钥)。
后端端点(生成上传URL):
typescript
const response = await fetch(
`https://api.cloudflare.com/client/v4/accounts/${accountId}/images/v2/direct_upload`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${apiToken}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
requireSignedURLs: true,
metadata: { userId: '12345' },
expiry: '2025-10-26T18:00:00Z' // 可选:默认30分钟,最长6小时
})
}
);
const { uploadURL, id } = await response.json();
// 将uploadURL返回给前端前端上传(HTML + JavaScript):
html
<form id="upload-form">
<input type="file" id="file-input" accept="image/*" />
<button type="submit">上传</button>
</form>
<script>
document.getElementById('upload-form').addEventListener('submit', async (e) => {
e.preventDefault();
const fileInput = document.getElementById('file-input');
const formData = new FormData();
formData.append('file', fileInput.files[0]); // 必须命名为'file'
const uploadURL = 'UPLOAD_URL_FROM_BACKEND'; // 从后端获取
const response = await fetch(uploadURL, {
method: 'POST',
body: formData // 无需设置Content-Type,浏览器会自动设为multipart/form-data
});
if (response.ok) {
console.log('上传成功!');
}
});
</script>重要性:
- 无需向浏览器暴露API密钥
- 用户直接上传至Cloudflare(速度更快,无需中间服务器)
- 一次性URL使用后或超时后失效
- 支持上传成功/失败通知的Webhooks
CORS问题关键修复:
- ✅ 正确做法: 使用编码(让浏览器自动设置请求头)
multipart/form-data - ✅ 正确做法: 文件字段命名为(而非
file或其他名称)image - ✅ 正确做法: 仅从后端调用API
/direct_upload - ❌ 错误做法: 设置或
Content-Type: application/jsonimage/jpeg - ❌ 错误做法: 从浏览器调用(会触发CORS失败)
/direct_upload
参考示例: , ,
templates/direct-creator-upload-backend.tstemplates/direct-creator-upload-frontend.htmlreferences/direct-upload-complete-workflow.mdImage Transformations
图片转换
URL Transformations
URL转换
Transform images using a special URL format.
URL Pattern:
https://<ZONE>/cdn-cgi/image/<OPTIONS>/<SOURCE-IMAGE>Example:
html
<img src="/cdn-cgi/image/width=800,quality=85,format=auto/uploads/photo.jpg" />Common Options:
- Sizing: ,
width=800,height=600fit=cover - Quality: (1-100)
quality=85 - Format: (WebP/AVIF auto-detection),
format=auto,format=webpformat=jpeg - Cropping: (smart crop),
gravity=auto,gravity=facetrim=10 - Effects: ,
blur=10,sharpen=3,brightness=1.2contrast=1.1 - Rotation: ,
rotate=90(horizontal),flip=h(vertical)flip=v
Fit Options:
- : Shrink to fit (never enlarge)
scale-down - : Resize to fit within dimensions (preserve aspect ratio)
contain - : Resize to fill dimensions (may crop)
cover - : Crop to exact dimensions
crop - : Resize and add padding (use with
padoption)background
Format Auto-Detection:
html
<img src="/cdn-cgi/image/format=auto/image.jpg" />Cloudflare serves:
- AVIF to browsers that support it (Chrome, Edge)
- WebP to browsers without AVIF support (Safari, Firefox)
- Original format (JPEG) as fallback
See: ,
templates/transform-via-url.tsreferences/transformation-options.md通过特殊URL格式转换图片。
URL格式:
https://<ZONE>/cdn-cgi/image/<OPTIONS>/<SOURCE-IMAGE>示例:
html
<img src="/cdn-cgi/image/width=800,quality=85,format=auto/uploads/photo.jpg" />常见选项:
- 尺寸调整: ,
width=800,height=600fit=cover - 质量设置: (取值范围1-100)
quality=85 - 格式转换: (自动检测WebP/AVIF支持),
format=auto,format=webpformat=jpeg - 裁剪: (智能裁剪),
gravity=auto,gravity=facetrim=10 - 特效: ,
blur=10,sharpen=3,brightness=1.2contrast=1.1 - 旋转: ,
rotate=90(水平翻转),flip=h(垂直翻转)flip=v
Fit选项说明:
- : 缩小至适配尺寸(绝不放大)
scale-down - : 调整大小以适配尺寸范围(保持宽高比)
contain - : 调整大小以填满尺寸范围(可能会裁剪)
cover - : 裁剪至精确尺寸
crop - : 调整大小并添加 padding(需配合
pad选项使用)background
格式自动检测:
html
<img src="/cdn-cgi/image/format=auto/image.jpg" />Cloudflare会根据浏览器支持情况返回对应格式:
- 向支持的浏览器(Chrome、Edge)返回AVIF
- 向不支持AVIF的浏览器(Safari、Firefox)返回WebP
- 作为回退返回原始格式(JPEG)
参考示例: ,
templates/transform-via-url.tsreferences/transformation-options.mdWorkers Transformations
Workers转换
Programmatic image transformations with custom URL schemes.
Basic Pattern:
typescript
export default {
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url);
// Custom URL scheme: /images/thumbnail/photo.jpg
if (url.pathname.startsWith('/images/thumbnail/')) {
const imagePath = url.pathname.replace('/images/thumbnail/', '');
const imageURL = `https://storage.example.com/${imagePath}`;
return fetch(imageURL, {
cf: {
image: {
width: 300,
height: 300,
fit: 'cover',
quality: 85
}
}
});
}
return new Response('Not found', { status: 404 });
}
};Advanced: Content Negotiation:
typescript
const accept = request.headers.get('accept') || '';
let format: 'avif' | 'webp' | 'auto' = 'auto';
if (/image\/avif/.test(accept)) {
format = 'avif';
} else if (/image\/webp/.test(accept)) {
format = 'webp';
}
return fetch(imageURL, {
cf: {
image: {
format,
width: 800,
quality: 85
}
}
});Why Workers Transformations:
- Custom URL schemes: Hide image storage location
- Preset names: Use ,
thumbnail,avatarinstead of pixel valueslarge - Content negotiation: Serve optimal format based on browser
- Access control: Check authentication before serving
- Dynamic sizing: Calculate dimensions based on device type
See: ,
templates/transform-via-workers.tsreferences/transformation-options.md通过自定义URL方案实现程序化图片转换。
基础格式:
typescript
export default {
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url);
// 自定义URL方案: /images/thumbnail/photo.jpg
if (url.pathname.startsWith('/images/thumbnail/')) {
const imagePath = url.pathname.replace('/images/thumbnail/', '');
const imageURL = `https://storage.example.com/${imagePath}`;
return fetch(imageURL, {
cf: {
image: {
width: 300,
height: 300,
fit: 'cover',
quality: 85
}
}
});
}
return new Response('未找到资源', { status: 404 });
}
};进阶:内容协商:
typescript
const accept = request.headers.get('accept') || '';
let format: 'avif' | 'webp' | 'auto' = 'auto';
if (/image\/avif/.test(accept)) {
format = 'avif';
} else if (/image\/webp/.test(accept)) {
format = 'webp';
}
return fetch(imageURL, {
cf: {
image: {
format,
width: 800,
quality: 85
}
}
});Workers转换的优势:
- 自定义URL方案: 隐藏图片存储位置
- 预设名称: 使用,
thumbnail,avatar等名称替代像素值large - 内容协商: 根据浏览器返回最优格式
- 访问控制: 在提供图片前验证用户身份
- 动态尺寸: 根据设备类型计算尺寸
参考示例: ,
templates/transform-via-workers.tsreferences/transformation-options.mdVariants Management
变体管理
Named Variants (Up to 100)
命名变体(最多100种)
Create predefined transformations for different use cases.
Create via API:
bash
curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/images/v1/variants" \
--header "Authorization: Bearer <API_TOKEN>" \
--header "Content-Type: application/json" \
--data '{
"id": "avatar",
"options": {
"fit": "cover",
"width": 200,
"height": 200,
"metadata": "none"
},
"neverRequireSignedURLs": false
}'Use in URLs:
html
<img src="https://imagedelivery.net/<ACCOUNT_HASH>/<IMAGE_ID>/avatar" />When to use:
- Consistent image sizes across your app
- Private images (works with signed URLs)
- Simple, predictable URLs
See:
templates/variants-management.ts为不同使用场景创建预定义转换规则。
通过API创建:
bash
curl "https://api.cloudflare.com/client/v4/accounts/{account_id}/images/v1/variants" \
--header "Authorization: Bearer <API_TOKEN>" \
--header "Content-Type: application/json" \
--data '{
"id": "avatar",
"options": {
"fit": "cover",
"width": 200,
"height": 200,
"metadata": "none"
},
"neverRequireSignedURLs": false
}'在URL中使用:
html
<img src="https://imagedelivery.net/<ACCOUNT_HASH>/<IMAGE_ID>/avatar" />适用场景:
- 应用中保持一致的图片尺寸
- 私有图片(可与签名URL配合使用)
- 简洁、可预测的URL
参考示例:
templates/variants-management.tsFlexible Variants
灵活变体
Dynamic transformations using params in URL.
Enable (per account, one-time):
bash
curl --request PATCH \
https://api.cloudflare.com/client/v4/accounts/{account_id}/images/v1/config \
--header "Authorization: Bearer <API_TOKEN>" \
--header "Content-Type: application/json" \
--data '{"flexible_variants": true}'Use in URLs:
html
<img src="https://imagedelivery.net/<ACCOUNT_HASH>/<IMAGE_ID>/w=400,sharpen=3" />When to use:
- Dynamic sizing needs
- Public images only (cannot use with signed URLs)
- Rapid prototyping
CRITICAL:
- ❌ Cannot use with
requireSignedURLs=true - ✅ Use named variants for private images
See:
references/variants-guide.md通过URL参数实现动态转换。
启用方式(按账户,一次性操作):
bash
curl --request PATCH \
https://api.cloudflare.com/client/v4/accounts/{account_id}/images/v1/config \
--header "Authorization: Bearer <API_TOKEN>" \
--header "Content-Type: application/json" \
--data '{"flexible_variants": true}'在URL中使用:
html
<img src="https://imagedelivery.net/<ACCOUNT_HASH>/<IMAGE_ID>/w=400,sharpen=3" />适用场景:
- 动态尺寸需求
- 仅公开图片(不可与签名URL配合使用)
- 快速原型开发
关键注意事项:
- ❌ 不可与配合使用
requireSignedURLs=true - ✅ 私有图片请使用命名变体
参考示例:
references/variants-guide.mdSigned URLs (Private Images)
签名URL(私有图片)
Generate time-limited URLs for private images using HMAC-SHA256 tokens.
URL Format:
https://imagedelivery.net/<ACCOUNT_HASH>/<IMAGE_ID>/<VARIANT>?exp=<EXPIRY>&sig=<SIGNATURE>Generate Signature (Workers example):
typescript
async function generateSignedURL(
imageId: string,
variant: string,
expirySeconds: number = 3600
): Promise<string> {
const accountHash = 'YOUR_ACCOUNT_HASH';
const signingKey = 'YOUR_SIGNING_KEY'; // Dashboard → Images → Keys
const expiry = Math.floor(Date.now() / 1000) + expirySeconds;
const stringToSign = `${imageId}${variant}${expiry}`;
const encoder = new TextEncoder();
const keyData = encoder.encode(signingKey);
const messageData = encoder.encode(stringToSign);
const cryptoKey = await crypto.subtle.importKey(
'raw',
keyData,
{ name: 'HMAC', hash: 'SHA-256' },
false,
['sign']
);
const signature = await crypto.subtle.sign('HMAC', cryptoKey, messageData);
const sig = Array.from(new Uint8Array(signature))
.map(b => b.toString(16).padStart(2, '0'))
.join('');
return `https://imagedelivery.net/${accountHash}/${imageId}/${variant}?exp=${expiry}&sig=${sig}`;
}Usage:
typescript
const signedURL = await generateSignedURL('image-id', 'public', 3600);
// Returns URL valid for 1 hourWhen to use:
- User profile photos (private until shared)
- Paid content (time-limited access)
- Temporary downloads
- Secure image delivery
See: ,
templates/signed-urls-generation.tsreferences/signed-urls-guide.md使用HMAC-SHA256令牌生成限时的私有图片访问URL。
URL格式:
https://imagedelivery.net/<ACCOUNT_HASH>/<IMAGE_ID>/<VARIANT>?exp=<EXPIRY>&sig=<SIGNATURE>生成签名(Workers示例):
typescript
async function generateSignedURL(
imageId: string,
variant: string,
expirySeconds: number = 3600
): Promise<string> {
const accountHash = 'YOUR_ACCOUNT_HASH';
const signingKey = 'YOUR_SIGNING_KEY'; // 控制台 → Images → 密钥
const expiry = Math.floor(Date.now() / 1000) + expirySeconds;
const stringToSign = `${imageId}${variant}${expiry}`;
const encoder = new TextEncoder();
const keyData = encoder.encode(signingKey);
const messageData = encoder.encode(stringToSign);
const cryptoKey = await crypto.subtle.importKey(
'raw',
keyData,
{ name: 'HMAC', hash: 'SHA-256' },
false,
['sign']
);
const signature = await crypto.subtle.sign('HMAC', cryptoKey, messageData);
const sig = Array.from(new Uint8Array(signature))
.map(b => b.toString(16).padStart(2, '0'))
.join('');
return `https://imagedelivery.net/${accountHash}/${imageId}/${variant}?exp=${expiry}&sig=${sig}`;
}使用示例:
typescript
const signedURL = await generateSignedURL('image-id', 'public', 3600);
// 返回有效期1小时的URL适用场景:
- 用户头像(仅在分享时可见)
- 付费内容(限时访问)
- 临时下载
- 安全的图片分发
参考示例: ,
templates/signed-urls-generation.tsreferences/signed-urls-guide.mdResponsive Images
响应式图片
Serve optimal image sizes for different screen sizes.
Using Named Variants:
html
<img
srcset="
https://imagedelivery.net/<HASH>/<ID>/mobile 480w,
https://imagedelivery.net/<HASH>/<ID>/tablet 768w,
https://imagedelivery.net/<HASH>/<ID>/desktop 1920w
"
sizes="(max-width: 480px) 480px, (max-width: 768px) 768px, 1920px"
src="https://imagedelivery.net/<HASH>/<ID>/desktop"
alt="Responsive image"
/>Using Flexible Variants:
html
<img
srcset="
https://imagedelivery.net/<HASH>/<ID>/w=480,f=auto 480w,
https://imagedelivery.net/<HASH>/<ID>/w=768,f=auto 768w,
https://imagedelivery.net/<HASH>/<ID>/w=1920,f=auto 1920w
"
sizes="(max-width: 480px) 480px, (max-width: 768px) 768px, 1920px"
src="https://imagedelivery.net/<HASH>/<ID>/w=1920,f=auto"
alt="Responsive image"
/>Art Direction (different crops for mobile vs desktop):
html
<picture>
<source
media="(max-width: 767px)"
srcset="https://imagedelivery.net/<HASH>/<ID>/mobile-square"
/>
<source
media="(min-width: 768px)"
srcset="https://imagedelivery.net/<HASH>/<ID>/desktop-wide"
/>
<img src="https://imagedelivery.net/<HASH>/<ID>/desktop-wide" alt="Hero image" />
</picture>See: ,
templates/responsive-images-srcset.htmlreferences/responsive-images-patterns.md为不同屏幕尺寸提供最优图片尺寸。
使用命名变体:
html
<img
srcset="
https://imagedelivery.net/<HASH>/<ID>/mobile 480w,
https://imagedelivery.net/<HASH>/<ID>/tablet 768w,
https://imagedelivery.net/<HASH>/<ID>/desktop 1920w
"
sizes="(max-width: 480px) 480px, (max-width: 768px) 768px, 1920px"
src="https://imagedelivery.net/<HASH>/<ID>/desktop"
alt="响应式图片"
/>使用灵活变体:
html
<img
srcset="
https://imagedelivery.net/<HASH>/<ID>/w=480,f=auto 480w,
https://imagedelivery.net/<HASH>/<ID>/w=768,f=auto 768w,
https://imagedelivery.net/<HASH>/<ID>/w=1920,f=auto 1920w
"
sizes="(max-width: 480px) 480px, (max-width: 768px) 768px, 1920px"
src="https://imagedelivery.net/<HASH>/<ID>/w=1920,f=auto"
alt="响应式图片"
/>艺术化适配(移动端与桌面端使用不同裁剪):
html
<picture>
<source
media="(max-width: 767px)"
srcset="https://imagedelivery.net/<HASH>/<ID>/mobile-square"
/>
<source
media="(min-width: 768px)"
srcset="https://imagedelivery.net/<HASH>/<ID>/desktop-wide"
/>
<img src="https://imagedelivery.net/<HASH>/<ID>/desktop-wide" alt="主视觉图片" />
</picture>参考示例: ,
templates/responsive-images-srcset.htmlreferences/responsive-images-patterns.mdCritical Rules
关键规则
Always Do
务必遵循
✅ Use for Direct Creator Upload
✅ Name the file field (not or other names)
✅ Call API from backend only (NOT browser)
✅ Use HTTPS URLs for transformations (HTTP not supported)
✅ URL-encode special characters in image paths
✅ Enable transformations on zone before using
✅ Use named variants for private images (signed URLs)
✅ Check header for transformation errors
✅ Set for automatic WebP/AVIF conversion
✅ Use to prevent unwanted enlargement
multipart/form-datafileimage/direct_upload/cdn-cgi/image/Cf-Resizedformat=autofit=scale-down✅ 直接创作者上传时使用
✅ 文件字段命名为(而非或其他名称)
✅ 仅从后端调用 API(而非浏览器)
✅ 转换使用HTTPS URL(不支持HTTP)
✅ 对图片路径中的特殊字符进行URL编码
✅ 使用前先在区域启用转换功能
✅ 私有图片使用命名变体(签名URL)
✅ 检查请求头排查转换错误
✅ 设置实现自动WebP/AVIF转换
✅ 使用避免意外放大
multipart/form-datafileimage/direct_upload/cdn-cgi/image/Cf-Resizedformat=autofit=scale-downNever Do
绝对禁止
❌ Use Content-Type for file uploads
❌ Call from browser (CORS will fail)
❌ Use flexible variants with
❌ Resize SVG files (they're inherently scalable)
❌ Use HTTP URLs for transformations (HTTPS only)
❌ Put spaces or unescaped Unicode in URLs
❌ Transform the same image multiple times in Workers (causes 9403 loop)
❌ Exceed 100 megapixels image size
❌ Use endpoint in Workers (use instead)
❌ Forget to enable transformations on zone before use
application/json/direct_uploadrequireSignedURLs=true/cdn-cgi/image/cf.image❌ 文件上传使用作为Content-Type
❌ 从浏览器调用(会触发CORS失败)
❌ 灵活变体与配合使用
❌ 调整SVG文件大小(SVG本身是矢量格式,可无限缩放)
❌ 转换使用HTTP URL(仅支持HTTPS)
❌ URL中包含空格或未转义的Unicode字符
❌ 在Workers中多次转换同一张图片(会触发9403循环错误)
❌ 图片尺寸超过1亿像素
❌ 在Workers中使用端点(请使用)
❌ 使用前忘记在区域启用转换功能
application/json/direct_uploadrequireSignedURLs=true/cdn-cgi/image/cf.imageKnown Issues Prevention
已知问题预防
This skill prevents 13+ documented issues.
本指南可预防**13+**种已记录的问题。
Issue #1: Direct Creator Upload CORS Error
问题1:直接创作者上传CORS错误
Error:
Access to XMLHttpRequest blocked by CORS policy: Request header field content-type is not allowedSource: Cloudflare Community #345739, #368114
Why It Happens: Server CORS settings only allow for Content-Type header
multipart/form-dataPrevention:
javascript
// ✅ CORRECT
const formData = new FormData();
formData.append('file', fileInput.files[0]);
await fetch(uploadURL, {
method: 'POST',
body: formData // Browser sets multipart/form-data automatically
});
// ❌ WRONG
await fetch(uploadURL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' }, // CORS error
body: JSON.stringify({ file: base64Image })
});错误信息:
Access to XMLHttpRequest blocked by CORS policy: Request header field content-type is not allowed问题原因: 服务器CORS设置仅允许作为Content-Type请求头
multipart/form-data预防方案:
javascript
// ✅ 正确做法
const formData = new FormData();
formData.append('file', fileInput.files[0]);
await fetch(uploadURL, {
method: 'POST',
body: formData // 浏览器会自动设置multipart/form-data
});
// ❌ 错误做法
await fetch(uploadURL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' }, // 触发CORS错误
body: JSON.stringify({ file: base64Image })
});Issue #2: Error 5408 - Upload Timeout
问题2:错误5408 - 上传超时
Error: after ~15 seconds of upload
Error 5408Source: Cloudflare Community #571336
Why It Happens: Cloudflare has 30-second request timeout; slow uploads or large files exceed limit
Prevention:
- Compress images before upload (client-side with Canvas API)
- Use reasonable file size limits (e.g., max 10MB)
- Show upload progress to user
- Handle timeout errors gracefully
javascript
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
if (file.size > MAX_FILE_SIZE) {
alert('File too large. Please select an image under 10MB.');
return;
}错误信息: 上传约15秒后出现
Error 5408问题原因: Cloudflare请求超时时间为30秒;上传速度过慢或文件过大导致超时
预防方案:
- 上传前在客户端压缩图片(使用Canvas API)
- 设置合理的文件大小限制(例如最大10MB)
- 向用户展示上传进度
- 优雅处理超时错误
javascript
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
if (file.size > MAX_FILE_SIZE) {
alert('文件过大,请选择10MB以下的图片。');
return;
}Issue #3: Error 400 - Invalid File Parameter
问题3:错误400 - 无效文件参数
Error: with unhelpful error message
400 Bad RequestSource: Cloudflare Community #487629
Why It Happens: File field must be named (not , , etc.)
fileimagephotoPrevention:
javascript
// ✅ CORRECT
formData.append('file', imageFile);
// ❌ WRONG
formData.append('image', imageFile); // 400 error
formData.append('photo', imageFile); // 400 error错误信息: 且无明确错误提示
400 Bad Request问题原因: 文件字段必须命名为(而非、等)
fileimagephoto预防方案:
javascript
// ✅ 正确做法
formData.append('file', imageFile);
// ❌ 错误做法
formData.append('image', imageFile); // 触发400错误
formData.append('photo', imageFile); // 触发400错误Issue #4: CORS Preflight Failures
问题4:CORS预检失败
Error: Preflight OPTIONS request blocked
Source: Cloudflare Community #306805
Why It Happens: Calling API directly from browser (should be backend-only)
/direct_uploadPrevention:
ARCHITECTURE:
Browser → Backend API → POST /direct_upload → Returns uploadURL → Browser uploads to uploadURLNever expose API token to browser. Generate upload URL on backend, return to frontend.
错误信息: OPTIONS预检请求被阻止
问题原因: 直接从浏览器调用 API(该API应仅从后端调用)
/direct_upload预防方案:
架构:
浏览器 → 后端API → POST /direct_upload → 返回uploadURL → 浏览器上传至uploadURL绝不能向浏览器暴露API令牌。在后端生成上传URL后返回给前端。
Issue #5: Error 9401 - Invalid Arguments
问题5:错误9401 - 参数无效
Error: - Required cf.image options missing or invalid
Cf-Resized: err=9401Why It Happens: Missing required transformation parameters or invalid values
Prevention:
typescript
// ✅ CORRECT
fetch(imageURL, {
cf: {
image: {
width: 800,
quality: 85,
format: 'auto'
}
}
});
// ❌ WRONG
fetch(imageURL, {
cf: {
image: {
width: 'large', // Must be number
quality: 150 // Max 100
}
}
});错误信息: - 缺少必要的cf.image选项或选项无效
Cf-Resized: err=9401问题原因: 缺少必要的转换参数或参数值无效
预防方案:
typescript
// ✅ 正确做法
fetch(imageURL, {
cf: {
image: {
width: 800,
quality: 85,
format: 'auto'
}
}
});
// ❌ 错误做法
fetch(imageURL, {
cf: {
image: {
width: 'large', // 必须是数字
quality: 150 // 最大值为100
}
}
});Issue #6: Error 9402 - Image Too Large
问题6:错误9402 - 图片过大
Error: - Image too large or connection interrupted
Cf-Resized: err=9402Why It Happens: Image exceeds maximum area (100 megapixels) or download fails
Prevention:
- Validate image dimensions before transforming
- Use reasonable source images (max 10000x10000px)
- Handle network errors gracefully
错误信息: - 图片过大或连接中断
Cf-Resized: err=9402问题原因: 图片超过最大面积限制(1亿像素)或下载失败
预防方案:
- 转换前验证图片尺寸
- 使用合理尺寸的源图片(最大10000x10000像素)
- 优雅处理网络错误
Issue #7: Error 9403 - Request Loop
问题7:错误9403 - 请求循环
Error: - Worker fetching its own URL or already-resized image
Cf-Resized: err=9403Why It Happens: Transformation applied to already-transformed image, or Worker fetches itself
Prevention:
typescript
// ✅ CORRECT
if (url.pathname.startsWith('/images/')) {
const originalPath = url.pathname.replace('/images/', '');
const originURL = `https://storage.example.com/${originalPath}`;
return fetch(originURL, { cf: { image: { width: 800 } } });
}
// ❌ WRONG
if (url.pathname.startsWith('/images/')) {
// Fetches worker's own URL, causes loop
return fetch(request, { cf: { image: { width: 800 } } });
}错误信息: - Worker请求自身URL或已转换过的图片
Cf-Resized: err=9403问题原因: 对已转换的图片再次应用转换,或Worker请求自身URL
预防方案:
typescript
// ✅ 正确做法
if (url.pathname.startsWith('/images/')) {
const originalPath = url.pathname.replace('/images/', '');
const originURL = `https://storage.example.com/${originalPath}`;
return fetch(originURL, { cf: { image: { width: 800 } } });
}
// ❌ 错误做法
if (url.pathname.startsWith('/images/')) {
// 请求Worker自身URL,触发循环
return fetch(request, { cf: { image: { width: 800 } } });
}Issue #8: Error 9406/9419 - Invalid URL Format
问题8:错误9406/9419 - URL格式无效
Error: or - Non-HTTPS URL or URL has spaces/unescaped Unicode
Cf-Resized: err=9406err=9419Why It Happens: Image URL uses HTTP (not HTTPS) or contains invalid characters
Prevention:
typescript
// ✅ CORRECT
const imageURL = "https://example.com/images/photo%20name.jpg";
// ❌ WRONG
const imageURL = "http://example.com/images/photo.jpg"; // HTTP not allowed
const imageURL = "https://example.com/images/photo name.jpg"; // Space not encodedAlways use for URL paths:
encodeURIComponent()typescript
const filename = "photo name.jpg";
const imageURL = `https://example.com/images/${encodeURIComponent(filename)}`;错误信息: 或 - 使用非HTTPS URL或URL包含空格/未转义Unicode字符
Cf-Resized: err=9406err=9419问题原因: 图片URL使用HTTP(而非HTTPS)或包含无效字符
预防方案:
typescript
// ✅ 正确做法
const imageURL = "https://example.com/images/photo%20name.jpg";
// ❌ 错误做法
const imageURL = "http://example.com/images/photo.jpg"; // 不支持HTTP
const imageURL = "https://example.com/images/photo name.jpg"; // 空格未编码务必对URL路径使用:
encodeURIComponent()typescript
const filename = "photo name.jpg";
const imageURL = `https://example.com/images/${encodeURIComponent(filename)}`;Issue #9: Error 9412 - Non-Image Response
问题9:错误9412 - 非图片响应
Error: - Origin returned HTML instead of image
Cf-Resized: err=9412Why It Happens: Origin server returns 404 page or error page (HTML) instead of image
Prevention:
typescript
// Verify URL before transforming
const originResponse = await fetch(imageURL, { method: 'HEAD' });
const contentType = originResponse.headers.get('content-type');
if (!contentType?.startsWith('image/')) {
return new Response('Not an image', { status: 400 });
}
return fetch(imageURL, { cf: { image: { width: 800 } } });错误信息: - 源服务器返回HTML而非图片
Cf-Resized: err=9412问题原因: 源服务器返回404页面或错误页面(HTML)而非图片
预防方案:
typescript
// 转换前验证URL
const originResponse = await fetch(imageURL, { method: 'HEAD' });
const contentType = originResponse.headers.get('content-type');
if (!contentType?.startsWith('image/')) {
return new Response('不是图片资源', { status: 400 });
}
return fetch(imageURL, { cf: { image: { width: 800 } } });Issue #10: Error 9413 - Max Image Area Exceeded
问题10:错误9413 - 图片面积超限
Error: - Image exceeds 100 megapixels
Cf-Resized: err=9413Why It Happens: Source image dimensions exceed 100 megapixels (e.g., 10000x10000px)
Prevention:
- Validate image dimensions before upload
- Pre-process oversized images
- Reject images above threshold
typescript
const MAX_MEGAPIXELS = 100;
if (width * height > MAX_MEGAPIXELS * 1_000_000) {
return new Response('Image too large', { status: 413 });
}错误信息: - 图片超过1亿像素
Cf-Resized: err=9413问题原因: 源图片尺寸超过1亿像素(例如10000x10000像素)
预防方案:
- 上传前验证图片尺寸
- 预处理超大尺寸图片
- 拒绝超过阈值的图片
typescript
const MAX_MEGAPIXELS = 100;
if (width * height > MAX_MEGAPIXELS * 1_000_000) {
return new Response('图片尺寸过大', { status: 413 });
}Issue #11: Flexible Variants + Signed URLs Incompatibility
问题11:灵活变体与签名URL不兼容
Error: Flexible variants don't work with private images
Why It Happens: Flexible variants cannot be used with
requireSignedURLs=truePrevention:
typescript
// ✅ CORRECT - Use named variants for private images
await uploadImage({
file: imageFile,
requireSignedURLs: true // Use named variants: /public, /avatar, etc.
});
// ❌ WRONG - Flexible variants don't support signed URLs
// Cannot use: /w=400,sharpen=3 with requireSignedURLs=true错误现象: 灵活变体无法用于私有图片
问题原因: 灵活变体不能与配合使用
requireSignedURLs=true预防方案:
typescript
// ✅ 正确做法 - 私有图片使用命名变体
await uploadImage({
file: imageFile,
requireSignedURLs: true // 使用命名变体: /public, /avatar等
});
// ❌ 错误做法 - 灵活变体不支持签名URL
// 无法配合requireSignedURLs=true使用/w=400,sharpen=3Issue #12: SVG Resizing Limitation
问题12:SVG文件调整大小限制
Error: SVG files don't resize via transformations
Why It Happens: SVG is inherently scalable (vector format), resizing not applicable
Prevention:
typescript
// SVGs can be served but not resized
// Use any variant name as placeholder
// https://imagedelivery.net/<HASH>/<SVG_ID>/public
// SVG will be served at original size regardless of variant settings错误现象: SVG文件无法通过转换调整大小
问题原因: SVG是矢量格式,本身可无限缩放,调整大小操作不适用
预防方案:
typescript
// SVG可正常提供但无法调整大小
// 使用任意变体名称作为占位符
// https://imagedelivery.net/<HASH>/<SVG_ID>/public
// 无论变体设置如何,SVG都会以原始尺寸提供Issue #13: EXIF Metadata Stripped by Default
问题13:默认移除EXIF元数据
Error: GPS data, camera settings removed from uploaded JPEGs
Why It Happens: Default behavior strips all metadata except copyright
Prevention:
typescript
// Preserve metadata
fetch(imageURL, {
cf: {
image: {
width: 800,
metadata: 'keep' // Options: 'none', 'copyright', 'keep'
}
}
});Options:
- : Strip all metadata
none - : Keep only copyright tag (default for JPEG)
copyright - : Preserve most EXIF metadata including GPS
keep
错误现象: 上传的JPEG文件中的GPS数据、相机设置等被移除
问题原因: 默认行为会移除除版权信息外的所有元数据
预防方案:
typescript
// 保留元数据
fetch(imageURL, {
cf: {
image: {
width: 800,
metadata: 'keep' // 选项: 'none', 'copyright', 'keep'
}
}
});选项说明:
- : 移除所有元数据
none - : 仅保留版权标签(JPEG默认设置)
copyright - : 保留大部分EXIF元数据,包括GPS信息
keep
Using Bundled Resources
配套资源使用
Templates (templates/)
模板文件(templates/)
Copy-paste ready code for common patterns:
- wrangler-images-binding.jsonc - Wrangler configuration (no binding needed)
- upload-api-basic.ts - Upload file to Images API
- upload-via-url.ts - Ingest image from external URL
- direct-creator-upload-backend.ts - Generate one-time upload URLs
- direct-creator-upload-frontend.html - User upload form
- transform-via-url.ts - URL transformation examples
- transform-via-workers.ts - Workers transformation patterns
- variants-management.ts - Create/list/delete variants
- signed-urls-generation.ts - HMAC-SHA256 signed URL generation
- responsive-images-srcset.html - Responsive image patterns
- batch-upload.ts - Batch API for high-volume uploads
Usage:
bash
cp templates/upload-api-basic.ts src/upload.ts可直接复制使用的常见场景代码:
- wrangler-images-binding.jsonc - Wrangler配置(无需绑定)
- upload-api-basic.ts - 通过Images API上传文件
- upload-via-url.ts - 从外部URL导入图片
- direct-creator-upload-backend.ts - 生成一次性上传URL
- direct-creator-upload-frontend.html - 用户上传表单
- transform-via-url.ts - URL转换示例
- transform-via-workers.ts - Workers转换模式
- variants-management.ts - 创建/列出/删除变体
- signed-urls-generation.ts - HMAC-SHA256签名URL生成
- responsive-images-srcset.html - 响应式图片模式
- batch-upload.ts - 批量上传API用于高容量上传
使用方式:
bash
cp templates/upload-api-basic.ts src/upload.tsEdit with your account ID and API token
替换为您的账户ID和API令牌
undefinedundefinedReferences (references/)
参考文档(references/)
In-depth documentation Claude can load as needed:
- api-reference.md - Complete API endpoints (upload, list, delete, variants)
- transformation-options.md - All transform params with examples
- variants-guide.md - Named vs flexible variants, when to use each
- signed-urls-guide.md - HMAC-SHA256 implementation details
- direct-upload-complete-workflow.md - Full architecture and flow
- responsive-images-patterns.md - srcset, sizes, art direction
- format-optimization.md - WebP/AVIF auto-conversion strategies
- top-errors.md - All 13+ errors with detailed troubleshooting
When to load:
- Deep-dive into specific feature
- Troubleshooting complex issues
- Understanding API details
- Implementing advanced patterns
Claude可按需加载的深度文档:
- api-reference.md - 完整API端点说明(上传、列出、删除、变体)
- transformation-options.md - 所有转换参数及示例
- variants-guide.md - 命名变体与灵活变体对比及适用场景
- signed-urls-guide.md - HMAC-SHA256实现细节
- direct-upload-complete-workflow.md - 完整架构与流程
- responsive-images-patterns.md - srcset、sizes、艺术化适配
- format-optimization.md - WebP/AVIF自动转换策略
- top-errors.md - 13+种错误及详细故障排除
加载时机:
- 深入了解特定功能
- 排查复杂问题
- 理解API细节
- 实现进阶模式
Scripts (scripts/)
脚本文件(scripts/)
check-versions.sh - Verify API endpoints are current
check-versions.sh - 验证API端点是否为最新版本
Advanced Topics
进阶主题
Custom Domains
自定义域名
Serve images from your own domain instead of .
imagedelivery.netURL Format:
https://example.com/cdn-cgi/imagedelivery/<ACCOUNT_HASH>/<IMAGE_ID>/<VARIANT>Requirements:
- Domain must be on Cloudflare (same account as Images)
- Proxied through Cloudflare (orange cloud)
Custom Paths (Transform Rules):
Rewrite to :
/images/.../cdn-cgi/imagedelivery/...- Dashboard → Rules → Transform Rules → Rewrite URL
- Match:
starts_with(http.request.uri.path, "/images/") - Rewrite:
/cdn-cgi/imagedelivery/<ACCOUNT_HASH>${substring(http.request.uri.path, 7)}
Now →
/images/{id}/{variant}/cdn-cgi/imagedelivery/{hash}/{id}/{variant}使用您自己的域名而非提供图片。
imagedelivery.netURL格式:
https://example.com/cdn-cgi/imagedelivery/<ACCOUNT_HASH>/<IMAGE_ID>/<VARIANT>要求:
- 域名必须在Cloudflare上(与Images服务同属一个账户)
- 通过Cloudflare代理(橙色云图标)
自定义路径(转换规则):
将重写为:
/images/.../cdn-cgi/imagedelivery/...- 控制台 → 规则 → 转换规则 → 重写URL
- 匹配条件:
starts_with(http.request.uri.path, "/images/") - 重写设置:
/cdn-cgi/imagedelivery/<ACCOUNT_HASH>${substring(http.request.uri.path, 7)}
现在 →
/images/{id}/{variant}/cdn-cgi/imagedelivery/{hash}/{id}/{variant}参考文档: 从自定义域名提供图片
Batch API
批量API
High-volume uploads with batch tokens.
Host: (instead of )
batch.imagedelivery.netapi.cloudflare.comUsage:
bash
undefined使用批量令牌实现高容量上传。
主机地址: (替代)
batch.imagedelivery.netapi.cloudflare.com使用方式:
bash
undefinedCreate batch token in dashboard: Images → Batch API
在控制台创建批量令牌: Images → 批量API
curl "https://batch.imagedelivery.net/images/v1"
--header "Authorization: Bearer <BATCH_TOKEN>"
--form 'file=@./image.jpg'
--header "Authorization: Bearer <BATCH_TOKEN>"
--form 'file=@./image.jpg'
**When to use**:
- Migrating thousands of images
- Bulk upload workflows
- Automated image ingestion
**See**: `templates/batch-upload.ts`curl "https://batch.imagedelivery.net/images/v1"
--header "Authorization: Bearer <BATCH_TOKEN>"
--form 'file=@./image.jpg'
--header "Authorization: Bearer <BATCH_TOKEN>"
--form 'file=@./image.jpg'
**适用场景**:
- 迁移数千张图片
- 批量上传工作流
- 自动化图片导入
**参考示例**: `templates/batch-upload.ts`Webhooks
Webhooks
Receive notifications for upload success/failure (Direct Creator Upload only).
Setup:
- Dashboard → Notifications → Destinations → Webhooks → Create
- Enter webhook URL and test
- Notifications → All Notifications → Add → Images → Select webhook
Payload (example):
json
{
"imageId": "2cdc28f0-017a-49c4-9ed7-87056c83901",
"status": "uploaded",
"metadata": {"userId": "12345"}
}When to use:
- Update database after upload
- Trigger image processing pipeline
- Notify user of upload status
See: Configure webhooks
接收上传成功/失败通知(仅适用于直接创作者上传)。
设置步骤:
- 控制台 → 通知 → 目标 → Webhooks → 创建
- 输入Webhook URL并测试
- 通知 → 所有通知 → 添加 → Images → 选择Webhook
Payload示例:
json
{
"imageId": "2cdc28f0-017a-49c4-9ed7-87056c83901",
"status": "uploaded",
"metadata": {"userId": "12345"}
}适用场景:
- 上传完成后更新数据库
- 触发图片处理流水线
- 通知用户上传状态
参考文档: 配置Webhooks
Troubleshooting
故障排除
Problem: Images not transforming
问题:图片未被转换
Symptoms: returns original image or 404
/cdn-cgi/image/...Solutions:
- Enable transformations on zone: Dashboard → Images → Transformations → Enable for zone
- Verify zone is proxied through Cloudflare (orange cloud)
- Check source image is publicly accessible
- Wait 5-10 minutes for settings to propagate
现象: 返回原始图片或404
/cdn-cgi/image/...解决方案:
- 在区域启用转换功能: 控制台 → Images → Transformations → 为区域启用
- 验证区域已通过Cloudflare代理(橙色云图标)
- 确认源图片可公开访问
- 等待5-10分钟让设置生效
Problem: Direct upload returns CORS error
问题:直接上传返回CORS错误
Symptoms: error in browser console
Access-Control-Allow-OriginSolutions:
- Use encoding (let browser set Content-Type)
multipart/form-data - Don't call from browser; call from backend
/direct_upload - Name file field (not
file)image - Remove manual Content-Type header
现象: 浏览器控制台出现错误
Access-Control-Allow-Origin解决方案:
- 使用编码(让浏览器自动设置Content-Type)
multipart/form-data - 不要从浏览器调用,从后端调用
/direct_upload - 文件字段命名为(而非
file)image - 移除手动设置的Content-Type请求头
Problem: Worker transformations return 9403 loop error
问题:Worker转换返回9403循环错误
Symptoms: in response headers
Cf-Resized: err=9403Solutions:
- Don't fetch Worker's own URL (use external origin)
- Don't transform already-resized images
- Check URL routing logic to avoid loops
现象: 响应头中出现
Cf-Resized: err=9403解决方案:
- 不要请求Worker自身URL(使用外部源)
- 不要对已转换的图片再次转换
- 检查URL路由逻辑避免循环
Problem: Signed URLs not working
问题:签名URL无法使用
Symptoms: 403 Forbidden when accessing signed URL
Solutions:
- Verify image uploaded with
requireSignedURLs=true - Check signature generation (HMAC-SHA256)
- Ensure expiry timestamp is in future
- Verify signing key matches dashboard (Images → Keys)
- Cannot use flexible variants with signed URLs (use named variants)
现象: 访问签名URL时返回403 Forbidden
解决方案:
- 确认图片上传时设置了
requireSignedURLs=true - 检查签名生成逻辑(HMAC-SHA256)
- 确保过期时间戳在未来
- 验证签名密钥与控制台一致(Images → 密钥)
- 签名URL无法配合灵活变体使用(请使用命名变体)
Problem: Images uploaded but not appearing
问题:图片已上传但未在控制台显示
Symptoms: Upload returns 200 OK but image not in dashboard
Solutions:
- Check for in response (Direct Creator Upload)
draft: true - Wait for upload to complete (check via GET )
/images/v1/{id} - Verify account ID matches
- Check for upload errors in webhooks
现象: 上传返回200 OK但控制台中看不到图片
解决方案:
- 检查响应中是否包含(直接创作者上传)
draft: true - 等待上传完成(通过GET 检查)
/images/v1/{id} - 确认账户ID匹配
- 检查Webhooks中的上传错误
Complete Setup Checklist
完整设置检查清单
- Cloudflare account with Images enabled
- Account ID and API token obtained (Images: Edit permission)
- (Optional) Image transformations enabled on zone
- (Optional) Variants created for common use cases
- (Optional) Flexible variants enabled if dynamic sizing needed
- (Optional) Signing key obtained for private images
- (Optional) Webhooks configured for upload notifications
- (Optional) Custom domain configured with Transform Rules
- Upload method implemented (file, URL, or direct creator)
- Serving URLs tested (imagedelivery.net or custom domain)
- Transformations tested (URL or Workers)
- Error handling implemented (CORS, timeouts, size limits)
- 已启用Images服务的Cloudflare账户
- 已获取账户ID和API令牌(拥有Images: Edit权限)
- (可选)已在区域启用图片转换功能
- (可选)已为常见场景创建变体
- (可选)已启用灵活变体以支持动态尺寸
- (可选)已获取私有图片签名密钥
- (可选)已配置上传通知Webhooks
- (可选)已配置自定义域名及转换规则
- 已实现上传方式(文件、URL或直接创作者上传)
- 已测试访问URL(imagedelivery.net或自定义域名)
- 已测试转换功能(URL或Workers)
- 已实现错误处理(CORS、超时、大小限制)
Official Documentation
官方文档
- Cloudflare Images: https://developers.cloudflare.com/images/
- Get Started: https://developers.cloudflare.com/images/get-started/
- Upload Images: https://developers.cloudflare.com/images/upload-images/
- Direct Creator Upload: https://developers.cloudflare.com/images/upload-images/direct-creator-upload/
- Transform Images: https://developers.cloudflare.com/images/transform-images/
- Transform via URL: https://developers.cloudflare.com/images/transform-images/transform-via-url/
- Transform via Workers: https://developers.cloudflare.com/images/transform-images/transform-via-workers/
- Create Variants: https://developers.cloudflare.com/images/manage-images/create-variants/
- Serve Private Images: https://developers.cloudflare.com/images/manage-images/serve-images/serve-private-images/
- Troubleshooting: https://developers.cloudflare.com/images/reference/troubleshooting/
- API Reference: https://developers.cloudflare.com/api/resources/images/
- Cloudflare Images: https://developers.cloudflare.com/images/
- 快速开始: https://developers.cloudflare.com/images/get-started/
- 上传图片: https://developers.cloudflare.com/images/upload-images/
- 直接创作者上传: https://developers.cloudflare.com/images/upload-images/direct-creator-upload/
- 转换图片: https://developers.cloudflare.com/images/transform-images/
- URL转换: https://developers.cloudflare.com/images/transform-images/transform-via-url/
- Workers转换: https://developers.cloudflare.com/images/transform-images/transform-via-workers/
- 创建变体: https://developers.cloudflare.com/images/manage-images/create-variants/
- 提供私有图片: https://developers.cloudflare.com/images/manage-images/serve-images/serve-private-images/
- 故障排除: https://developers.cloudflare.com/images/reference/troubleshooting/
- API参考: https://developers.cloudflare.com/api/resources/images/
Package Versions (Verified 2025-10-26)
版本信息(2025-10-26验证)
API Version: v2 (for direct uploads), v1 (for standard uploads)
No npm packages required - uses native Cloudflare APIs
Optional:
- - TypeScript types for Workers
@cloudflare/workers-types@latest
Questions? Issues?
- Check for common issues
references/top-errors.md - Verify all steps in the setup process
- Check official docs: https://developers.cloudflare.com/images/
- Ensure transformations are enabled on zone
- Verify CORS setup for Direct Creator Upload
API版本: v2(直接上传), v1(标准上传)
无需npm包 - 使用原生Cloudflare APIs
可选依赖:
- - Workers的TypeScript类型定义
@cloudflare/workers-types@latest
有疑问?遇到问题?
- 查看了解常见问题
references/top-errors.md - 验证设置流程中的所有步骤
- 查看官方文档: https://developers.cloudflare.com/images/
- 确认已在区域启用转换功能
- 验证直接创作者上传的CORS设置