| # 文件上传指南 (File Upload Guide) | |
| 这份文档详细说明如何上传文件到 Cloudflare Pages 和 Workers。 | |
| This guide explains how to upload files to Cloudflare Pages and Workers in detail. | |
| --- | |
| ## 目录 (Table of Contents) | |
| 1. [上传文件到 Pages](#上传文件到-pages) | |
| 2. [上传文件到 Worker](#上传文件到-worker) | |
| 3. [API 详细说明](#api-详细说明) | |
| 4. [完整示例代码](#完整示例代码) | |
| --- | |
| ## 上传文件到 Pages | |
| ### 方法 1: 从本地目录部署 (Deploy from Local Directory) | |
| 这是最简单的方法,会自动扫描目录并上传所有文件。 | |
| ```python | |
| from cloudflare_manager import CloudflareManager, CloudflareAccount | |
| # 初始化账户 | |
| account = CloudflareAccount( | |
| email="your-email@example.com", | |
| token="your-api-token" | |
| ) | |
| cf = CloudflareManager(account) | |
| # 先创建项目(如果还没有创建) | |
| cf.create_pages_project("my-website", "main") | |
| # 从目录部署(上传所有文件) | |
| cf.deploy_pages_project( | |
| project_name="my-website", | |
| directory="./my-site", # 本地目录路径 | |
| branch="main", # 分支名称 | |
| commit_message="Initial deploy" # 提交信息 | |
| ) | |
| ``` | |
| ### 工作原理 (How It Works) | |
| `deploy_pages_project` 方法会: | |
| 1. 扫描指定目录下的所有文件 | |
| 2. 计算每个文件的 SHA-256 哈希值 | |
| 3. 构建 manifest(文件清单) | |
| 4. 使用 `multipart/form-data` 格式上传所有文件 | |
| 5. 返回部署详情 | |
| ### 上传的数据格式 | |
| ```python | |
| # 内部实现的数据格式 | |
| files = [ | |
| ("branch", (None, "main")), | |
| ("commit_message", (None, "Deploy via API")), | |
| ("manifest", (None, '{"index.html": "abc123...", "style.css": "def456..."}')), | |
| ("index.html", ("index.html", file_content, "text/html")), | |
| ("style.css", ("style.css", file_content, "text/css")), | |
| # ... 更多文件 | |
| ] | |
| ``` | |
| ### 支持的文件类型 | |
| 所有常见的 Web 文件类型都支持: | |
| - HTML: `.html`, `.htm` | |
| - CSS: `.css` | |
| - JavaScript: `.js`, `.mjs` | |
| - 图片: `.png`, `.jpg`, `.jpeg`, `.gif`, `.svg`, `.ico` | |
| - 字体: `.woff`, `.woff2`, `.ttf`, `.otf` | |
| - JSON: `.json` | |
| - 文本: `.txt`, `.md` | |
| --- | |
| ## 上传文件到 Worker | |
| ### 基本用法 | |
| 上传 Worker 脚本非常简单: | |
| ```python | |
| from cloudflare_manager import CloudflareManager, CloudflareAccount | |
| # 初始化账户 | |
| account = CloudflareAccount( | |
| email="your-email@example.com", | |
| token="your-api-token" | |
| ) | |
| cf = CloudflareManager(account) | |
| # 上传 Worker 脚本 | |
| cf.upload_worker( | |
| script_name="my-worker", | |
| worker_file="./worker.js" | |
| ) | |
| ``` | |
| ### 带绑定的高级用法 (Advanced Usage with Bindings) | |
| 如果你的 Worker 需要绑定 KV、R2 或其他资源: | |
| ```python | |
| # KV 命名空间绑定 | |
| bindings = [ | |
| { | |
| "type": "kv_namespace", | |
| "name": "MY_KV", | |
| "namespace_id": "your-kv-namespace-id" | |
| } | |
| ] | |
| cf.upload_worker( | |
| script_name="my-worker", | |
| worker_file="./worker.js", | |
| bindings=bindings | |
| ) | |
| ``` | |
| ### Worker 文件示例 | |
| 创建一个简单的 Worker 文件 `worker.js`: | |
| ```javascript | |
| // worker.js | |
| export default { | |
| async fetch(request, env, ctx) { | |
| return new Response('Hello from Cloudflare Worker!', { | |
| headers: { 'Content-Type': 'text/plain' } | |
| }); | |
| } | |
| } | |
| ``` | |
| ### 上传的数据格式 | |
| ```python | |
| # 内部实现 | |
| metadata = { | |
| "main_module": "_worker.js", | |
| "compatibility_date": "2023-01-01", | |
| "bindings": [] # 可选的绑定 | |
| } | |
| files = { | |
| 'metadata': (None, json.dumps(metadata), 'application/json'), | |
| '_worker.js': ('_worker.js', worker_content, 'text/javascript'), | |
| } | |
| ``` | |
| --- | |
| ## API 详细说明 | |
| ### deploy_pages_project() | |
| **功能**: 从本地目录部署 Pages 项目 | |
| **参数**: | |
| - `project_name` (str): 项目名称 | |
| - `directory` (str): 本地目录路径 | |
| - `branch` (str, 默认="main"): 分支名称 | |
| - `commit_message` (str, 默认="Deploy via API"): 提交信息 | |
| **返回值**: | |
| - `Dict`: 部署详情(成功时) | |
| - `None`: 失败时 | |
| **示例**: | |
| ```python | |
| result = cf.deploy_pages_project( | |
| project_name="my-website", | |
| directory="./dist", | |
| branch="main", | |
| commit_message="Update homepage" | |
| ) | |
| if result: | |
| print(f"部署 ID: {result['id']}") | |
| print(f"URL: {result['url']}") | |
| print(f"状态: {result['latest_stage']['status']}") | |
| ``` | |
| ### upload_worker() | |
| **功能**: 上传 Worker 脚本 | |
| **参数**: | |
| - `script_name` (str): Worker 脚本名称 | |
| - `worker_file` (str): Worker .js 文件路径 | |
| - `bindings` (List[Dict], 可选): 资源绑定列表 | |
| **返回值**: | |
| - `Dict`: Worker 详情(成功时) | |
| - `None`: 失败时 | |
| **示例**: | |
| ```python | |
| result = cf.upload_worker( | |
| script_name="api-worker", | |
| worker_file="./api.js", | |
| bindings=[ | |
| { | |
| "type": "kv_namespace", | |
| "name": "CACHE", | |
| "namespace_id": "abc123..." | |
| } | |
| ] | |
| ) | |
| if result: | |
| print(f"Worker ID: {result['id']}") | |
| print(f"创建时间: {result['created_on']}") | |
| ``` | |
| ### list_workers() | |
| **功能**: 列出所有 Worker 脚本 | |
| **参数**: 无 | |
| **返回值**: `List[Dict]` - Worker 列表 | |
| **示例**: | |
| ```python | |
| workers = cf.list_workers() | |
| for worker in workers: | |
| print(f"- {worker['id']}") | |
| ``` | |
| ### get_worker() | |
| **功能**: 获取指定 Worker 的详细信息 | |
| **参数**: | |
| - `script_name` (str): Worker 脚本名称 | |
| **返回值**: | |
| - `Dict`: Worker 详情(成功时) | |
| - `None`: 失败时 | |
| **示例**: | |
| ```python | |
| worker = cf.get_worker("my-worker") | |
| if worker: | |
| print(f"脚本名称: {worker['id']}") | |
| print(f"修改时间: {worker['modified_on']}") | |
| ``` | |
| ### delete_worker() | |
| **功能**: 删除 Worker 脚本 | |
| **参数**: | |
| - `script_name` (str): Worker 脚本名称 | |
| **返回值**: `bool` - 成功返回 True,失败返回 False | |
| **示例**: | |
| ```python | |
| if cf.delete_worker("old-worker"): | |
| print("Worker 已删除") | |
| ``` | |
| --- | |
| ## 完整示例代码 | |
| ### 示例 1: 部署静态网站到 Pages | |
| ```python | |
| #!/usr/bin/env python3 | |
| from cloudflare_manager import CloudflareManager, CloudflareAccount | |
| import os | |
| # 配置账户 | |
| account = CloudflareAccount( | |
| email="your-email@example.com", | |
| token="your-api-token" | |
| ) | |
| cf = CloudflareManager(account) | |
| # 项目名称 | |
| project_name = "my-blog" | |
| # 创建 Pages 项目 | |
| print("📝 创建 Pages 项目...") | |
| cf.create_pages_project(project_name, "main") | |
| # 部署网站 | |
| print("📦 部署网站...") | |
| result = cf.deploy_pages_project( | |
| project_name=project_name, | |
| directory="./public", # Hugo/Jekyll 等的输出目录 | |
| branch="main", | |
| commit_message="Deploy blog v1.0" | |
| ) | |
| if result: | |
| print(f"✅ 部署成功!") | |
| print(f"访问地址: {result['url']}") | |
| else: | |
| print("❌ 部署失败") | |
| ``` | |
| ### 示例 2: 上传 Worker API | |
| ```python | |
| #!/usr/bin/env python3 | |
| from cloudflare_manager import CloudflareManager, CloudflareAccount | |
| # 配置账户 | |
| account = CloudflareAccount( | |
| email="your-email@example.com", | |
| token="your-api-token" | |
| ) | |
| cf = CloudflareManager(account) | |
| # 创建 Worker 文件 | |
| worker_code = ''' | |
| export default { | |
| async fetch(request, env, ctx) { | |
| const url = new URL(request.url); | |
| if (url.pathname === '/api/hello') { | |
| return new Response(JSON.stringify({ | |
| message: 'Hello from Worker!', | |
| timestamp: new Date().toISOString() | |
| }), { | |
| headers: { 'Content-Type': 'application/json' } | |
| }); | |
| } | |
| return new Response('404 Not Found', { status: 404 }); | |
| } | |
| } | |
| ''' | |
| # 保存到文件 | |
| with open('api-worker.js', 'w', encoding='utf-8') as f: | |
| f.write(worker_code) | |
| # 上传 Worker | |
| print("📤 上传 Worker...") | |
| result = cf.upload_worker( | |
| script_name="api-worker", | |
| worker_file="api-worker.js" | |
| ) | |
| if result: | |
| print("✅ Worker 上传成功!") | |
| print(f"可以通过 https://api-worker.{account.name}.workers.dev 访问") | |
| else: | |
| print("❌ Worker 上传失败") | |
| ``` | |
| ### 示例 3: Worker + KV 存储 | |
| ```python | |
| #!/usr/bin/env python3 | |
| from cloudflare_manager import CloudflareManager, CloudflareAccount | |
| account = CloudflareAccount( | |
| email="your-email@example.com", | |
| token="your-api-token" | |
| ) | |
| cf = CloudflareManager(account) | |
| # Worker 代码(使用 KV) | |
| worker_code = ''' | |
| export default { | |
| async fetch(request, env, ctx) { | |
| const key = new URL(request.url).pathname.slice(1) || 'counter'; | |
| // 从 KV 读取 | |
| let count = await env.MY_KV.get(key); | |
| count = count ? parseInt(count) : 0; | |
| // 增加计数 | |
| count++; | |
| // 写入 KV | |
| await env.MY_KV.put(key, count.toString()); | |
| return new Response(`访问次数: ${count}`, { | |
| headers: { 'Content-Type': 'text/plain; charset=utf-8' } | |
| }); | |
| } | |
| } | |
| ''' | |
| with open('counter-worker.js', 'w', encoding='utf-8') as f: | |
| f.write(worker_code) | |
| # 上传带 KV 绑定的 Worker | |
| print("📤 上传 Worker (with KV)...") | |
| result = cf.upload_worker( | |
| script_name="counter-worker", | |
| worker_file="counter-worker.js", | |
| bindings=[ | |
| { | |
| "type": "kv_namespace", | |
| "name": "MY_KV", | |
| "namespace_id": "your-kv-namespace-id" # 替换为你的 KV ID | |
| } | |
| ] | |
| ) | |
| if result: | |
| print("✅ Worker (with KV) 上传成功!") | |
| ``` | |
| ### 示例 4: 批量部署多个 Workers | |
| ```python | |
| #!/usr/bin/env python3 | |
| from cloudflare_manager import CloudflareManager, CloudflareAccount | |
| import os | |
| account = CloudflareAccount( | |
| email="your-email@example.com", | |
| token="your-api-token" | |
| ) | |
| cf = CloudflareManager(account) | |
| # Worker 文件列表 | |
| workers = [ | |
| ("api-worker", "./workers/api.js"), | |
| ("auth-worker", "./workers/auth.js"), | |
| ("cache-worker", "./workers/cache.js"), | |
| ] | |
| print("📤 批量上传 Workers...") | |
| for name, filepath in workers: | |
| if os.path.exists(filepath): | |
| print(f"\n上传: {name} <- {filepath}") | |
| result = cf.upload_worker(name, filepath) | |
| if result: | |
| print(f" ✅ {name} 上传成功") | |
| else: | |
| print(f" ❌ {name} 上传失败") | |
| else: | |
| print(f" ⚠️ 文件不存在: {filepath}") | |
| print("\n✅ 批量上传完成!") | |
| ``` | |
| --- | |
| ## 常见问题 (FAQ) | |
| ### Q1: Pages 部署支持哪些文件大小? | |
| A: 单个文件最大 25MB,总部署大小最大 20,000 个文件。 | |
| ### Q2: Worker 脚本有大小限制吗? | |
| A: 免费计划限制 1MB,付费计划(Workers Bundled)限制 5MB。 | |
| ### Q3: 如何处理大型项目? | |
| A: 对于大型项目,建议: | |
| 1. 使用构建工具(Webpack、Rollup)打包和压缩 | |
| 2. 排除 `node_modules` 等不必要的目录 | |
| 3. 使用 `.gitignore` 风格的过滤 | |
| ### Q4: 上传失败怎么办? | |
| A: 检查: | |
| 1. API Token 权限是否正确 | |
| 2. 文件路径是否存在 | |
| 3. 文件格式是否正确 | |
| 4. 网络连接是否正常 | |
| ### Q5: 如何查看上传进度? | |
| A: 目前库会在上传时打印文件数量。对于大型部署,建议使用 `tqdm` 等进度条库。 | |
| --- | |
| ## 技术细节 (Technical Details) | |
| ### Pages 部署 API | |
| **端点**: `POST /accounts/{account_id}/pages/projects/{project_name}/deployments` | |
| **请求格式**: `multipart/form-data` | |
| **必需字段**: | |
| - `manifest`: JSON 字符串,包含文件名到哈希的映射 | |
| - `branch`: 分支名称 | |
| - 各个文件字段 | |
| **示例请求**: | |
| ```python | |
| files = [ | |
| ("manifest", (None, '{"index.html": "sha256-hash..."}')), | |
| ("branch", (None, "main")), | |
| ("index.html", ("index.html", file_content, "text/html")), | |
| ] | |
| ``` | |
| ### Worker 上传 API | |
| **端点**: `PUT /accounts/{account_id}/workers/scripts/{script_name}` | |
| **请求格式**: `multipart/form-data` | |
| **必需字段**: | |
| - `metadata`: JSON 字符串,包含元数据和绑定 | |
| - `_worker.js`: Worker 脚本内容 | |
| **示例请求**: | |
| ```python | |
| files = { | |
| 'metadata': (None, json.dumps({ | |
| "main_module": "_worker.js", | |
| "compatibility_date": "2023-01-01" | |
| }), 'application/json'), | |
| '_worker.js': ('_worker.js', worker_content, 'text/javascript'), | |
| } | |
| ``` | |
| --- | |
| ## 相关文档 | |
| - [API 参考手册](./API_REFERENCE.md) | |
| - [使用指南](./USAGE_GUIDE.md) | |
| - [快速开始](./GET_STARTED.md) | |
| - [项目概述](./README.md) | |
| --- | |
| ## 总结 | |
| 这份指南覆盖了: | |
| ✅ Pages 文件部署(从目录上传) | |
| ✅ Worker 脚本上传 | |
| ✅ Worker 资源绑定(KV、R2 等) | |
| ✅ 完整的示例代码 | |
| ✅ API 详细说明 | |
| ✅ 常见问题解答 | |
| 如有其他问题,请查看 [API_REFERENCE.md](./API_REFERENCE.md) 或提交 Issue。 | |