cloudflare-images
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCloudflare Images
Cloudflare Images
Status: Production Ready ✅
Last Updated: 2026-01-21
Dependencies: Cloudflare account with Images enabled
Latest Versions: Cloudflare Images API v2, @cloudflare/workers-types@4.20260108.0
Recent Updates (2025):
- February 2025: Content Credentials support (C2PA standard) - preserve image provenance chains, automatic cryptographic signing of transformations
- August 2025: AI Face Cropping GA (with
gravity=facecontrol, GPU-based RetinaFace, 99.4% precision)zoom - May 2025: Media Transformations origin restrictions (default: same-domain only, configurable via dashboard)
- Upcoming: Background removal, generative upscale (planned features)
Deprecation Notice: Mirage deprecated September 15, 2025. Migrate to Cloudflare Images for storage/transformations or use native for lazy loading.
<img loading="lazy">状态:已就绪可用于生产环境 ✅
最后更新时间:2026-01-21
依赖项:已启用Images功能的Cloudflare账户
最新版本:Cloudflare Images API v2, @cloudflare/workers-types@4.20260108.0
2025年近期更新:
- 2025年2月:支持内容凭证(C2PA标准)- 保留图片来源链,自动对转换操作进行加密签名
- 2025年8月:AI人脸裁剪正式可用(搭配
gravity=face控制,基于GPU的RetinaFace算法,准确率99.4%)zoom - 2025年5月:媒体转换源限制(默认:仅允许同域,可通过控制台配置)
- 即将推出:背景移除、生成式放大(规划中功能)
弃用通知:Mirage已于2025年9月15日弃用。请迁移至Cloudflare Images进行存储/转换,或使用原生实现懒加载。
<img loading="lazy">Overview
概述
Two features: Images API (upload/store with variants) and Image Transformations (resize any image via URL or Workers).
包含两大功能:Images API(上传/存储图片并创建变体)和图片转换(通过URL或Workers调整任意图片)。
Quick Start
快速开始
1. Enable: Dashboard → Images → Get Account ID + API token (Cloudflare Images: Edit permission)
2. Upload:
bash
curl -X POST https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/images/v1 \
-H 'Authorization: Bearer <API_TOKEN>' \
-H 'Content-Type: multipart/form-data' \
-F 'file=@./image.jpg'3. Serve:
https://imagedelivery.net/<ACCOUNT_HASH>/<IMAGE_ID>/public4. Transform (optional): Dashboard → Images → Transformations → Enable for zone
html
<img src="/cdn-cgi/image/width=800,quality=85/uploads/photo.jpg" />1. 启用服务:进入控制台(Dashboard)→ Images → 获取账户ID和API令牌(需Cloudflare Images的编辑权限)
2. 上传图片:
bash
curl -X POST https://api.cloudflare.com/client/v4/accounts/<ACCOUNT_ID>/images/v1 \
-H 'Authorization: Bearer <API_TOKEN>' \
-H 'Content-Type: multipart/form-data' \
-F 'file=@./image.jpg'3. 提供访问:
https://imagedelivery.net/<ACCOUNT_HASH>/<IMAGE_ID>/public4. 转换图片(可选):控制台 → Images → Transformations → 为当前区域启用该功能
html
<img src="/cdn-cgi/image/width=800,quality=85/uploads/photo.jpg" />Upload Methods
上传方式
1. File Upload: POST to with (multipart/form-data), optional , ,
/images/v1fileidrequireSignedURLsmetadata2. Upload via URL: POST with (supports HTTP basic auth)
url=https://example.com/image.jpg3. Direct Creator Upload (one-time URLs, no API key exposure):
Backend: POST to → returns
Frontend: POST file to with FormData
/images/v2/direct_uploaduploadURLuploadURLCRITICAL CORS FIX:
- ✅ Use (let browser set header)
multipart/form-data - ✅ Name field (NOT
file)image - ✅ Call from backend only
/direct_upload - ❌ Don't set
Content-Type: application/json - ❌ Don't call from browser
/direct_upload
1. 文件上传:向发送POST请求,携带参数(multipart/form-data格式),可选参数包括、、
/images/v1fileidrequireSignedURLsmetadata2. 通过URL上传:发送POST请求并携带(支持HTTP基础认证)
url=https://example.com/image.jpg3. 创作者直接上传(一次性URL,无需暴露API密钥):
后端:向发送POST请求 → 返回
前端:向发送包含FormData的POST请求以上传文件
/images/v2/direct_uploaduploadURLuploadURL关键CORS修复:
- ✅ 使用格式(由浏览器自动设置请求头)
multipart/form-data - ✅ 文件字段命名为(不能是
file)image - ✅ 仅从后端调用接口(禁止从浏览器调用)
/direct_upload - ❌ 不要设置
Content-Type: application/json - ❌ 不要从浏览器调用
/direct_upload
Image Transformations
图片转换
URL:
/cdn-cgi/image/<OPTIONS>/<SOURCE>- Sizing:
width=800,height=600,fit=cover - Quality: (1-100)
quality=85 - Format: (WebP/AVIF auto-detection)
format=auto - Cropping: (smart crop),
gravity=auto(AI face detection, Aug 2025 GA),gravity=face,gravity=center(0-1 range, face crop tightness)zoom=0.5 - Effects:
blur=10,sharpen=3,brightness=1.2 - Fit: ,
scale-down,contain,cover,croppad
Workers: Use object in fetch
cf.imagetypescript
fetch(imageURL, {
cf: {
image: { width: 800, quality: 85, format: 'auto', gravity: 'face', zoom: 0.8 }
}
});URL格式:
/cdn-cgi/image/<OPTIONS>/<SOURCE>- 尺寸调整:
width=800,height=600,fit=cover - 质量设置:(范围1-100)
quality=85 - 格式:(自动检测并转换为WebP/AVIF)
format=auto - 裁剪:(智能裁剪)、
gravity=auto(AI人脸检测,2025年8月正式可用)、gravity=face、gravity=center(范围0-1,控制人脸裁剪的紧凑程度)zoom=0.5 - 特效:
blur=10,sharpen=3,brightness=1.2 - 适配方式:、
scale-down、contain、cover、croppad
Workers中使用:在fetch请求中使用对象
cf.imagetypescript
fetch(imageURL, {
cf: {
image: { width: 800, quality: 85, format: 'auto', gravity: 'face', zoom: 0.8 }
}
});Variants
图片变体
Named Variants (up to 100): Predefined transformations (e.g., , )
avatarthumbnail- Create: POST to with
/images/v1/variants,idoptions - Use:
imagedelivery.net/<HASH>/<ID>/avatar - Works with signed URLs
Flexible Variants: Dynamic params in URL ()
w=400,sharpen=3- Enable: PATCH with
/images/v1/config{"flexible_variants": true} - ❌ Cannot use with signed URLs (use named variants instead)
命名变体(最多100个):预定义的转换规则(例如、)
avatarthumbnail- 创建:向发送POST请求,携带
/images/v1/variants和idoptions - 使用:
imagedelivery.net/<HASH>/<ID>/avatar - 支持签名URL
灵活变体:在URL中传递动态参数()
w=400,sharpen=3- 启用:向发送PATCH请求,携带
/images/v1/config{"flexible_variants": true} - ❌ 不能与签名URL配合使用(请改用命名变体)
Signed URLs
签名URL
Generate HMAC-SHA256 tokens for private images (URL format: ).
?exp=<TIMESTAMP>&sig=<HMAC>Algorithm: → hex signature
HMAC-SHA256(signingKey, imageId + variant + expiry)See: for Workers implementation
templates/signed-urls-generation.ts为私有图片生成HMAC-SHA256令牌(URL格式:)。
?exp=<TIMESTAMP>&sig=<HMAC>算法: → 十六进制签名
HMAC-SHA256(signingKey, imageId + variant + expiry)参考实现:中的Workers实现代码
templates/signed-urls-generation.tsCritical 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✅ 创作者直接上传时使用格式
✅ 文件字段命名为(不能是或其他名称)
✅ 仅从后端调用接口(禁止从浏览器调用)
✅ 转换图片时使用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 16 documented issues.
本技能可预防16个已记录的问题。
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请求被阻止
原因:直接从浏览器调用接口(该接口仅允许后端调用)
/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 Format
问题13:格式转换导致EXIF元数据丢失
Error: GPS data, camera settings removed from uploaded images
Why It Happens: Default behavior strips all metadata except copyright. CRITICAL: WebP and PNG output formats ALWAYS discard metadata regardless of settings - only JPEG supports metadata preservation.
Prevention:
typescript
// ✅ CORRECT - JPEG preserves metadata
fetch(imageURL, {
cf: {
image: {
width: 800,
format: 'jpeg', // or 'auto' (may become jpeg)
metadata: 'keep' // Preserves most EXIF including GPS
}
}
});
// ❌ WRONG - WebP/PNG ignore metadata setting
fetch(imageURL, {
cf: {
image: {
format: 'webp',
metadata: 'keep' // NO EFFECT - always stripped for WebP/PNG
}
}
});Metadata Options (JPEG only):
- : Strip all metadata
none - : Keep only copyright tag (default for JPEG)
copyright - : Preserve most EXIF metadata including GPS
keep
Format Support:
- ✅ JPEG: All metadata options work
- ❌ WebP: Always strips metadata (acts as )
none - ❌ PNG: Always strips metadata (acts as )
none
错误信息:上传的图片丢失GPS数据、相机设置等元数据
原因:默认行为会剥离除版权信息外的所有元数据。重点:WebP和PNG输出格式无论如何设置都会丢弃元数据 - 只有JPEG格式支持保留元数据。
解决方案:
typescript
// ✅ 正确做法 - JPEG格式保留元数据
fetch(imageURL, {
cf: {
image: {
width: 800,
format: 'jpeg', // 或'auto'(可能自动转为jpeg)
metadata: 'keep' // 保留大部分EXIF元数据,包括GPS信息
}
}
});
// ❌ 错误做法 - WebP/PNG忽略元数据设置
fetch(imageURL, {
cf: {
image: {
format: 'webp',
metadata: 'keep' // 无效 - WebP始终会剥离元数据
}
}
});元数据选项(仅适用于JPEG):
- : 剥离所有元数据
none - : 仅保留版权标签(JPEG默认设置)
copyright - : 保留大部分EXIF元数据,包括GPS信息
keep
格式支持:
- ✅ JPEG: 所有元数据选项均有效
- ❌ WebP: 始终剥离元数据(等同于)
none - ❌ PNG: 始终剥离元数据(等同于)
none
Issue #14: AVIF Resolution Limit Ambiguity
问题14:AVIF分辨率限制不明确
Error: Large AVIF transformations fail or degrade to lower resolution
Source: Cloudflare Docs + Community Report
Why It Happens: Official docs state 1,600px hard limit for , but community reports indicate practical limit of 1200px for longest side as of late 2024. Note: Discrepancy between official docs (1600px) and reported behavior (1200px) needs verification.
format=avifPrevention:
typescript
// ✅ RECOMMENDED - Use format=auto instead of explicit avif
fetch(imageURL, {
cf: {
image: {
width: 2000,
format: 'auto' // Cloudflare chooses best format
}
}
});
// ⚠️ MAY FAIL - Explicit AVIF with large dimensions
fetch(imageURL, {
cf: {
image: {
width: 2000,
format: 'avif' // May fail if >1200px
}
}
});
// ✅ WORKAROUND - Use WebP for larger images
if (width > 1200) {
format = 'webp'; // WebP supports larger dimensions
} else {
format = 'avif'; // AVIF for smaller images
}错误信息:大尺寸AVIF转换失败或分辨率降低
来源:Cloudflare文档 + 社区反馈
原因:官方文档说明的硬限制为1600像素,但社区反馈截至2024年末,实际最长边限制为1200像素。注意:官方文档(1600px)与实际行为(1200px)存在差异,需进一步验证。
format=avif解决方案:
typescript
// ✅ 推荐做法 - 使用format=auto而非显式设置avif
fetch(imageURL, {
cf: {
image: {
width: 2000,
format: 'auto' // Cloudflare自动选择最佳格式
}
}
});
// ⚠️ 可能失败 - 显式设置AVIF且尺寸较大
fetch(imageURL, {
cf: {
image: {
width: 2000,
format: 'avif' // 若尺寸超过1200px可能失败
}
}
});
// ✅ 替代方案 - 大尺寸图片使用WebP
if (width > 1200) {
format = 'webp'; // WebP支持更大尺寸
} else {
format = 'avif'; // 小尺寸图片使用AVIF
}Issue #15: Image Cache by Device Type (Community-reported)
问题15:按设备类型缓存图片(社区反馈)
Error: Desktop and mobile see different cached versions, unexpected cache misses
Source: Cloudflare Community
Why It Happens: Images are cached by device type unexpectedly with no configuration option to disable this behavior in cache rules. Multiple users confirm this behavior as of Dec 2024.
Prevention:
- Understand that purging cache requires purging for each device type
- Use manual cache purging per device type via Cloudflare dashboard
- Account for device-specific caching in cache invalidation strategies
Solution/Workaround:
Manual cache purging per device type via Cloudflare dashboard when needed.
错误信息:桌面端和移动端看到不同的缓存版本,出现意外的缓存未命中
来源:Cloudflare社区
原因:图片会按设备类型进行意外缓存,且缓存规则中没有禁用该行为的配置选项。截至2024年12月,已有多位用户确认此行为。
解决方案:
- 了解清除缓存时需要针对每个设备类型分别操作
- 通过Cloudflare控制台手动按设备类型清除缓存
- 在缓存失效策略中考虑设备特定缓存的影响
解决方法/替代方案:
必要时通过Cloudflare控制台手动按设备类型清除缓存。
Issue #16: PNG Not Cached by Default
问题16:PNG图片默认不被缓存
Error: PNG images not caching despite other image formats working
Source: Cloudflare Community
Why It Happens: Default file extensions cached by Cloudflare do NOT include . Default cached extensions: , , , , , , , , (PNG is missing).
.png.jpg.jpeg.gif.webp.bmp.ico.svg.tif.tiffPrevention:
Create explicit cache rule for PNG files:
- Dashboard → Caching → Cache Rules
- Add rule:
URI Pathends with→ Cache Everything.png
错误信息:PNG图片未被缓存,其他图片格式正常
来源:Cloudflare社区
原因:Cloudflare默认缓存的文件扩展名不包含。默认缓存的扩展名包括:, , , , , , , , (缺少PNG)。
.png.jpg.jpeg.gif.webp.bmp.ico.svg.tif.tiff解决方案:
为PNG文件创建显式缓存规则:
- 控制台 → 缓存 → 缓存规则
- 添加规则:
URI路径结尾为→ 缓存所有内容.png
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 from your domain via (requires domain on Cloudflare, proxied). Use Transform Rules for custom paths.
/cdn-cgi/imagedelivery/<HASH>/<ID>/<VARIANT>Batch API: High-volume uploads via with batch tokens (Dashboard → Images → Batch API)
batch.imagedelivery.netWebhooks: Notifications for Direct Creator Upload (Dashboard → Notifications → Webhooks). Payload includes , , .
imageIdstatusmetadataContent Credentials (C2PA): Cloudflare Images preserves and signs image provenance chains. When transforming images with Content Credentials, Cloudflare automatically appends transformations to the manifest and cryptographically signs them using DigiCert certificates. Enable via Dashboard → Images → Transformations → Preserve Content Credentials. Note: Only works if source images already contain C2PA metadata (certain cameras, DALL-E, compatible editing software). Verify at contentcredentials.org/verify.
Browser Cache TTL: Default Browser Cache TTL is 2 days (172,800 seconds). Customizable from 1 hour to 1 year (account-level or per-variant). Important: Private images (signed URLs) do NOT respect TTL settings. Can cause issues when re-uploading images with same Custom ID - users may see old version for up to 2 days. Solution: Use unique image IDs (append timestamp/hash) or manually purge cache after re-upload.
Product Merge Migration (Nov 2023): Cloudflare merged Image Resizing into Images product with new pricing: $0.50 per 1,000 unique transformations monthly (billing once per 30 days per unique transformation). Migration Gotchas: Old Image Resizing bills based on uncached requests (unpredictable costs due to variable cache behavior). New billing is per "unique transformation" (image ID + params combination), not request count. Same transformation requested 1,000 times/month = billed once. Existing customers can continue using legacy version or migrate voluntarily.
R2 Integration for Cost Optimization: Cloudflare Images is built on R2 + Image Resizing. For cost savings, store original images in R2 and use Image Transformations on-demand:
- Upload images to R2 bucket
- Serve via custom domain with transformations
/cdn-cgi/image/ - No variants stored (transformations are ephemeral/cached)
Cost Comparison:
- R2: 10GB storage + unlimited bandwidth (free tier)
- Cloudflare Images: $5/month (100k images) + $1 per 100k transformations
- R2 + Transformations: R2 storage + $0.50 per 1k unique transformations
Use Case: If you don't need named variants, batch uploads, or Direct Creator Upload features, R2 is more cost-effective.
Example Workers Pattern with R2:
typescript
export default {
async fetch(request, env) {
const url = new URL(request.url);
const imageKey = url.pathname.replace('/images/', '');
const originURL = `https://r2-bucket.example.com/${imageKey}`;
return fetch(originURL, {
cf: {
image: {
width: 800,
quality: 85,
format: 'auto'
}
}
});
}
};Reference: Cloudflare Reference Architecture
自定义域名:通过从你的域名提供图片访问(要求域名已接入Cloudflare且处于代理模式)。可使用转换规则配置自定义路径。
/cdn-cgi/imagedelivery/<HASH>/<ID>/<VARIANT>批量API:通过使用批量令牌进行高批量上传(控制台 → Images → Batch API)
batch.imagedelivery.netWebhooks:创作者直接上传的通知(控制台 → 通知 → Webhooks)。Payload包含、、。
imageIdstatusmetadata内容凭证(C2PA):Cloudflare Images保留并签名图片来源链。当转换包含内容凭证的图片时,Cloudflare会自动将转换操作添加到清单中,并使用DigiCert证书进行加密签名。可通过控制台 → Images → Transformations → 保留内容凭证启用该功能。注意:仅当源图片已包含C2PA元数据时有效(部分相机、DALL-E、兼容的编辑软件支持)。可在contentcredentials.org/verify验证。
浏览器缓存TTL:默认浏览器缓存TTL为2天(172800秒)。可在账户级别或变体级别自定义,范围从1小时到1年。重点:私有图片(签名URL)不遵守TTL设置。如果使用相同的自定义ID重新上传图片,用户可能会在长达2天内看到旧版本。解决方案:使用唯一的图片ID(附加时间戳/哈希值)或重新上传后手动清除缓存。
产品合并迁移(2023年11月):Cloudflare将Image Resizing合并到Images产品中,新定价为:每月每1000次唯一转换收费0.5美元(每30天按唯一转换次数计费)。迁移注意事项:旧版Image Resizing根据未缓存请求次数计费(由于缓存行为不可预测,成本可能波动)。新定价按“唯一转换”次数计费(图片ID+参数的组合),同一转换每月被请求1000次仅计费1次。现有客户可继续使用旧版本或自愿迁移。
R2集成优化成本:Cloudflare Images基于R2 + Image Resizing构建。为节省成本,可将原始图片存储在R2中,按需使用转换功能:
- 将图片上传到R2存储桶
- 通过自定义域名配合转换功能提供访问
/cdn-cgi/image/ - 无需存储变体(转换操作是临时的/可缓存的)
成本对比:
- R2:10GB存储 + 无限带宽(免费层)
- Cloudflare Images:每月5美元(10万张图片) + 每10万次转换收费1美元
- R2 + 转换功能:R2存储费用 + 每1000次唯一转换收费0.5美元
适用场景:如果不需要命名变体、批量上传或创作者直接上传功能,R2更具成本效益。
Workers与R2集成示例:
typescript
export default {
async fetch(request, env) {
const url = new URL(request.url);
const imageKey = url.pathname.replace('/images/', '');
const originURL = `https://r2-bucket.example.com/${imageKey}`;
return fetch(originURL, {
cf: {
image: {
width: 800,
quality: 85,
format: 'auto'
}
}
});
}
};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 → Keys)
- 不能将灵活变体与签名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中的上传错误
Problem: Re-uploaded image still shows old version
问题:重新上传图片后仍显示旧版本
Symptoms: Even users who never visited page see old image after re-upload
Solutions:
- Use unique image IDs for each upload: ${baseId}-${Date.now()}`;`
const imageId = \ - Set shorter Cache-Control headers (e.g., max-age=86400 for 1 day instead of 30 days)
- Manual purge via dashboard after re-upload with same ID
- Understand default Browser Cache TTL is 2 days - users may see cached version
Root Cause: Cloudflare respects origin Cache-Control headers. If origin sets long max-age (e.g., 30 days), images remain cached even after re-upload with same ID.
症状:即使是从未访问过页面的用户,重新上传后仍看到旧图片
解决方案:
- 每次上传使用唯一的图片ID:${baseId}-${Date.now()}
const imageId =; - 设置更短的Cache-Control请求头(例如max-age=86400,即1天,而非30天)
- 使用相同ID重新上传后手动清除控制台中的缓存
- 了解默认浏览器缓存TTL为2天 - 用户可能会看到缓存的旧版本
根本原因:Cloudflare遵守源服务器的Cache-Control请求头。如果源服务器设置了较长的max-age(例如30天),即使重新上传相同ID的图片,旧版本仍会被缓存。
Problem: PNG images not caching
问题:PNG图片未被缓存
Symptoms: PNG images bypass cache while other formats (JPEG, WebP) cache correctly
Solutions:
- Create explicit cache rule: Dashboard → Caching → Cache Rules
- Add rule:
URI Pathends with→ Cache Everything.png - Default cached extensions don't include (only
.png,.jpg,.jpeg,.gif,.webp,.bmp,.ico,.svg,.tif).tiff
症状:PNG图片绕过缓存,而其他格式(JPEG、WebP)缓存正常
解决方案:
- 创建显式缓存规则:控制台 → 缓存 → 缓存规则
- 添加规则:
URI路径结尾为→ 缓存所有内容.png - 默认缓存扩展名不包含(仅包含
.png,.jpg,.jpeg,.gif,.webp,.bmp,.ico,.svg,.tif).tiff
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
包版本
Last Verified: 2026-01-21
API Version: v2 (direct uploads), v1 (standard uploads)
Optional: @cloudflare/workers-types@4.20260108.0
Skill Version: 2.1.0 | Changes: Added 3 new issues (AVIF limits, cache by device, PNG caching), enhanced metadata issue with format details, added Content Credentials, Browser Cache TTL, Product Merge notes, R2 integration pattern, Mirage deprecation notice, and cache troubleshooting guidance. Error count: 13 → 16.
最后验证时间:2026-01-21
API版本: v2(直接上传), v1(标准上传)
可选依赖: @cloudflare/workers-types@4.20260108.0
技能版本: 2.1.0 | 更新内容: 新增3个问题(AVIF限制、按设备缓存、PNG缓存),增强元数据问题的格式细节说明,添加内容凭证、浏览器缓存TTL、产品合并说明、R2集成模式、Mirage弃用通知及缓存故障排查指南。错误数量:13 → 16。