展开本页目录
开始前准备什么
- 服务端保存自己的 API Key;准备认证、每用户配额和独立存储目录。
- 上传入口先设置请求体上限,再在应用里分块检查;文件名、MIME 都不能当成解码证明。
- 准备数据库与持久 worker,写清 queued、submitting、saved、unknown 和 failed 的状态转换。
- 固定当前 Images 型号和字段,通过已有 Python SDK 验证一次最小调用。
- 接收上传
- 解码与暂存
- 创建任务
- worker 请求
- 保存与查询
供 FastAPI 或 Next.js 业务层采用的接口设计,不是供应商已支持的异步 API。
UploadFile 解决接收方式,验证还要自己做
20 MiB 是本教程示例的应用限制,不是所有模型的官方上限。读取后用受限图片解码器确认 PNG/JPEG/WebP、实际宽高、像素量和帧数;不合格文件在创建付费任务前拒绝。UploadFile 的暂存机制不免除反向代理、应用和磁盘配额。
分块读取片段:需配套认证、反向代理限额与图片解码
from fastapi import HTTPException, UploadFile
MAX_BYTES = 20 * 1024 * 1024
async def read_bounded(upload: UploadFile) -> bytes:
data = bytearray()
try:
while chunk := await upload.read(64 * 1024):
if len(data) + len(chunk) > MAX_BYTES:
raise HTTPException(413, "image exceeds application limit")
data.extend(chunk)
finally:
await upload.close()
if not data:
raise HTTPException(400, "empty image")
return bytes(data)HTTP 服务把上传和生成拆成两个动作
创建接口不能接受任意服务器文件路径或任意内网 URL。素材从已授权 input_id 读取,输出名称由服务器生成;从供应商返回 URL 下载时做域名、重定向、大小和超时控制,避免把下载器开放成通用代理。
| 动作 | 输入与返回 | 完成条件 |
|---|---|---|
| 上传素材 | multipart 文件 → 受控 input_id | 真实解码通过,暂存文件写入成功 |
| 创建图片任务 | input_id / prompt / request_key → job_id | 用户配额和素材归属通过,业务键唯一 |
| 查询任务 | job_id → 状态和结果元数据 | 仅返回当前用户拥有的任务 |
| 下载结果 | job_id → 自己保存的完整文件 | 真实格式、宽高、字节与哈希可查 |
- 动作
- 上传素材
- 输入与返回
- multipart 文件 → 受控 input_id
- 完成条件
- 真实解码通过,暂存文件写入成功
- 动作
- 创建图片任务
- 输入与返回
- input_id / prompt / request_key → job_id
- 完成条件
- 用户配额和素材归属通过,业务键唯一
- 动作
- 查询任务
- 输入与返回
- job_id → 状态和结果元数据
- 完成条件
- 仅返回当前用户拥有的任务
- 动作
- 下载结果
- 输入与返回
- job_id → 自己保存的完整文件
- 完成条件
- 真实格式、宽高、字节与哈希可查
worker 提交一次,状态落库后再做后续动作
- 创建任务前核对输入存在、输出路径可写、空间和预算;入队之后先原子领取任务,防止两个 worker 同时提交。
- 在提交前记录 submitting 和时间。SDK 关闭隐式生成重试;请求超时后记 unknown,保留请求标识和已有数据。
- 收到图片后先保存原始字节,完整解码再记录实际尺寸。保存失败优先重试本地写入,不能把已成功的任务重新送给模型。
- 把错误正文做脱敏与长度限制后存储;向浏览器只返回可读原因和业务 ID,不返回服务器路径、认证头或上游堆栈。
何时用 BackgroundTasks,何时用持久队列
本页没有提供完整认证或队列实现。若只有单人本地试验,可先同步调用并设置明确超时;上线为多人服务前补持久任务、限额和权限,不能把本地演示代码标为生产方案。
| 工作 | 建议执行处 | 原因 |
|---|---|---|
| 更新轻量审计记录或清理标记 | 可用进程内 BackgroundTasks | 允许进程退出后按计划补做 |
| 需要付费的图片提交与结果保存 | 持久队列和独立 worker | 要追踪崩溃、并发和重复提交 |
| CPU 较重的图像解码或合成 | 受限 worker 进程 | 不阻塞 HTTP 服务并控制资源 |
| 用户查询已存在的任务 | 普通 GET 接口 | 无需重新执行生成任务 |
- 工作
- 更新轻量审计记录或清理标记
- 建议执行处
- 可用进程内 BackgroundTasks
- 原因
- 允许进程退出后按计划补做
- 工作
- 需要付费的图片提交与结果保存
- 建议执行处
- 持久队列和独立 worker
- 原因
- 要追踪崩溃、并发和重复提交
- 工作
- CPU 较重的图像解码或合成
- 建议执行处
- 受限 worker 进程
- 原因
- 不阻塞 HTTP 服务并控制资源
- 工作
- 用户查询已存在的任务
- 建议执行处
- 普通 GET 接口
- 原因
- 无需重新执行生成任务
先验证 HTTP 行为,再检查图片结果
- 空文件、伪图片、超大字节数和过大像素输入应在提交前失败;记下供应商调用次数为 0。
- 同时提交相同用户与 request_key,业务表应只有一个任务;同一 Key 携带不同内容应报冲突。
- 模拟 worker 在提交后退出,任务不能自动恢复成 ready;通过调用记录决定结果状态。
- 模拟对象存储故障、他人任务读取和过期素材,确认分别返回可追溯错误。
- 完成离线流程后,只用一张授权素材真实调用,核对返回文件、usage 与实际账单。
怎样确认已经完成
- 上传时有限额,实际图片完整解码通过。
- 服务端持有 Key,认证与结果归属已验证。
- 并发 worker 和相同请求键不会重复提交。
- unknown 与明确失败分开,进程重启不会盲目重提。
- 真实返回图片已保存并重新打开,费用只引用核对过的账单。
常见问题
UploadFile 会自动验证图片吗?
不会。它提供文件接收和暂存接口,文件名与 content_type 由上传方声明;应用仍需检查实际字节、解码、像素量和资源限额。
BackgroundTasks 可以做长期生图队列吗?
进程内任务不提供完整的持久队列语义。需要跨进程恢复、并发领取和付费提交追踪时,应使用持久任务存储与独立 worker。