Claude Files API 深入:从上传、复用到配额管理的工程化指南
如果你在生产环境用 Claude 处理任何带"文档"的业务——合同问答、发票识别、代码审查、数据分析——很快会撞到一个共同问题:同一份文件被反复 base64 编码塞进请求。一份 5MB 的 PDF 每次调用上传一次,base64 编码膨胀到 6.6MB,10 万次请求就是 660GB 的无效带宽,token 计费上也按全量重新计算。
Files API 就是为这个场景设计的:上传一次拿到 file_id,后续所有请求只引用 ID。听起来简单,但接入时一堆细节会被忽略——beta header 怎么带、配额怎么算、文件能不能跨 API key 复用、删不删除、和 Batch / MCP / Code Execution 怎么配合。本文把这些都讲清楚。
所有代码示例使用 claudeapi.com 的国内接入点 https://gw.claudeapi.com,避免国内直连 api.anthropic.com 的超时问题。Files API 在国内中转和官方 API 上行为完全一致,只是入口换了。
一、Files API 解决的核心问题
把同一份文件反复塞进请求会带来三个具体损失:
| 损失 | 表现 | Files API 怎么解决 |
|---|---|---|
| 带宽 | base64 比原始字节多 33%,每次上传都重传 | 一次上传,后续只传 file_id(几十字节) |
| 延迟 | 大文件上传占据请求首段时间 | file_id 引用是常数时间 |
| 编排复杂度 | 多用户共享同一文档时各传一份 | 同 workspace 内 file_id 可被任意 API key 引用 |
注意:Files API 不能省 token——文件被引用时仍按原文 token 量计费,省的是网络传输和编码开销,以及"重复上传"这种纯浪费。要真正省 token 还得叠加 prompt caching。
现状(截至 2026-05)
Files API 仍处于 beta 阶段,调用必须带 header anthropic-beta: files-api-2025-04-14。Anthropic 在 2026 年的官方路线图里提过会在年内 GA,但接口形态可能微调,生产接入时建议把这个 header 抽成常量集中管理,以便未来一处修改。
支持的平台:Claude API 直接调用、Claude Platform on AWS、Microsoft Foundry。不支持 Amazon Bedrock 和 Vertex AI(来源:Anthropic Files API 官方文档)。
二、生命周期:上传、引用、删除
2.1 上传
import anthropic
client = anthropic.Anthropic(
api_key="sk-你的ClaudeAPI密钥",
base_url="https://gw.claudeapi.com",
default_headers={"anthropic-beta": "files-api-2025-04-14"},
)
with open("annual_report.pdf", "rb") as f:
uploaded = client.beta.files.upload(
file=("annual_report.pdf", f, "application/pdf")
)
print(uploaded)
# File(
# id='file_011CNha8iCJcU1wXNR6q4V8w',
# type='file',
# filename='annual_report.pdf',
# mime_type='application/pdf',
# size_bytes=2456789,
# created_at='2026-05-23T08:12:33Z',
# downloadable=False
# )
import anthropic
client = anthropic.Anthropic(
api_key="sk-你的ClaudeAPI密钥",
base_url="https://gw.claudeapi.com",
default_headers={"anthropic-beta": "files-api-2025-04-14"},
)
with open("annual_report.pdf", "rb") as f:
uploaded = client.beta.files.upload(
file=("annual_report.pdf", f, "application/pdf")
)
print(uploaded)
# File(
# id='file_011CNha8iCJcU1wXNR6q4V8w',
# type='file',
# filename='annual_report.pdf',
# mime_type='application/pdf',
# size_bytes=2456789,
# created_at='2026-05-23T08:12:33Z',
# downloadable=False
# )
返回对象里要关注三个字段:
id:后续所有引用的句柄size_bytes:累加到组织 100GB 配额downloadable:用户上传的文件 不能下载(恒为False),只有 skill 或 code-execution 生成的文件可下载
2.2 引用
response = client.messages.create(
model="claude-opus-4-7",
max_tokens=4096,
extra_headers={"anthropic-beta": "files-api-2025-04-14"},
messages=[
{
"role": "user",
"content": [
{
"type": "document",
"source": {"type": "file", "file_id": uploaded.id},
},
{"type": "text", "text": "概述本报告的财务关键指标。"},
],
}
],
)
response = client.messages.create(
model="claude-opus-4-7",
max_tokens=4096,
extra_headers={"anthropic-beta": "files-api-2025-04-14"},
messages=[
{
"role": "user",
"content": [
{
"type": "document",
"source": {"type": "file", "file_id": uploaded.id},
},
{"type": "text", "text": "概述本报告的财务关键指标。"},
],
}
],
)
content block 类型按文件类型选择:
| 文件类型 | content block type | source.type |
|---|---|---|
document |
file |
|
| 图片(PNG/JPEG/GIF/WebP) | image |
file |
| CSV/Excel(搭配 code execution) | container_upload |
— |
| 源码文件(搭配 code execution) | container_upload |
— |
2.3 列出与删除
# 分页列出
files = client.beta.files.list(limit=100)
for f in files.data:
print(f.id, f.filename, f.size_bytes, f.created_at)
# 删除单个
client.beta.files.delete("file_011CNha8iCJcU1wXNR6q4V8w")
# 分页列出
files = client.beta.files.list(limit=100)
for f in files.data:
print(f.id, f.filename, f.size_bytes, f.created_at)
# 删除单个
client.beta.files.delete("file_011CNha8iCJcU1wXNR6q4V8w")
重要:删除是不可逆的,且不会回滚之前用该 file_id 完成的请求记录。但如果有任何进行中的 Batch 任务还在引用这个 file_id,删除会让 Batch 任务报错。删除前用 list 接口或自己的本地索引确认没有引用方。
2.4 cURL 三件套
# 上传
curl https://gw.claudeapi.com/v1/files \
-H "x-api-key: sk-你的ClaudeAPI密钥" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: files-api-2025-04-14" \
-F "file=@annual_report.pdf;type=application/pdf"
# 列出
curl https://gw.claudeapi.com/v1/files \
-H "x-api-key: sk-你的ClaudeAPI密钥" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: files-api-2025-04-14"
# 删除
curl -X DELETE https://gw.claudeapi.com/v1/files/file_xxx \
-H "x-api-key: sk-你的ClaudeAPI密钥" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: files-api-2025-04-14"
# 上传
curl https://gw.claudeapi.com/v1/files \
-H "x-api-key: sk-你的ClaudeAPI密钥" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: files-api-2025-04-14" \
-F "file=@annual_report.pdf;type=application/pdf"
# 列出
curl https://gw.claudeapi.com/v1/files \
-H "x-api-key: sk-你的ClaudeAPI密钥" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: files-api-2025-04-14"
# 删除
curl -X DELETE https://gw.claudeapi.com/v1/files/file_xxx \
-H "x-api-key: sk-你的ClaudeAPI密钥" \
-H "anthropic-version: 2023-06-01" \
-H "anthropic-beta: files-api-2025-04-14"
三、配额:500MB 单文件、100GB 组织
| 维度 | 限制 |
|---|---|
| 单文件大小 | 500 MB |
| 组织(workspace)总存储 | 100 GB |
| 文件名长度 | 1-255 字符 |
| 文件名禁止字符 | 路径分隔符 / \、控制字符 |
| Zero Data Retention | 不适用——Files API 不在 ZDR 覆盖范围 |
100GB 看着多,但生产环境很快就能爆——一个客服 SaaS 一天上传 5000 份 1MB 的工单截图,20 天就 100GB。配额管理要做两件事:前置去重和定期清理。
3.1 前置去重:SHA-256 + 本地索引
每次上传前先算 hash,命中已上传文件直接复用 file_id,不重复上传。
import hashlib
import sqlite3
def get_or_upload(file_path: str, client) -> str:
with open(file_path, "rb") as f:
content = f.read()
digest = hashlib.sha256(content).hexdigest()
# 查本地 hash → file_id 索引
db = sqlite3.connect("file_index.db")
db.execute("CREATE TABLE IF NOT EXISTS files (hash TEXT PRIMARY KEY, file_id TEXT)")
row = db.execute("SELECT file_id FROM files WHERE hash = ?", (digest,)).fetchone()
if row:
return row[0]
# 未命中,上传并入库
uploaded = client.beta.files.upload(
file=(file_path, content, "application/pdf")
)
db.execute("INSERT INTO files VALUES (?, ?)", (digest, uploaded.id))
db.commit()
return uploaded.id
import hashlib
import sqlite3
def get_or_upload(file_path: str, client) -> str:
with open(file_path, "rb") as f:
content = f.read()
digest = hashlib.sha256(content).hexdigest()
# 查本地 hash → file_id 索引
db = sqlite3.connect("file_index.db")
db.execute("CREATE TABLE IF NOT EXISTS files (hash TEXT PRIMARY KEY, file_id TEXT)")
row = db.execute("SELECT file_id FROM files WHERE hash = ?", (digest,)).fetchone()
if row:
return row[0]
# 未命中,上传并入库
uploaded = client.beta.files.upload(
file=(file_path, content, "application/pdf")
)
db.execute("INSERT INTO files VALUES (?, ?)", (digest, uploaded.id))
db.commit()
return uploaded.id
陷阱:本地 hash 索引和 Anthropic 服务器的真实状态可能不同步——你删除了 file_id 但本地索引没更新。生产环境每周跑一次"对账",让本地索引和 client.beta.files.list() 的实际结果保持一致。
3.2 清理策略:按用途分类
不是所有文件都该长期保留。按用途打 tag 用不同的清理周期:
| 文件用途 | 保留策略 |
|---|---|
| 用户主动上传的"我的文档库" | 用户删除时同步删除 |
| 工单/客服截图 | 30 天 TTL,自动删除 |
| 一次性问答的临时文件 | 调用完立即删除 |
| 全局共享的标准文档(产品手册、SOP) | 永久保留,放白名单 |
Anthropic 服务端没有 TTL 字段——TTL 要靠本地 created_at + 定时任务实现。
3.3 监控配额
files = client.beta.files.list(limit=1000)
total_bytes = sum(f.size_bytes for f in files.data)
print(f"已用: {total_bytes / 1024**3:.2f} GB / 100 GB")
print(f"文件数: {len(files.data)}")
files = client.beta.files.list(limit=1000)
total_bytes = sum(f.size_bytes for f in files.data)
print(f"已用: {total_bytes / 1024**3:.2f} GB / 100 GB")
print(f"文件数: {len(files.data)}")
接到 Grafana / Prometheus 里,设置 80% 配额告警。
四、与其他能力的协同
Files API 真正发挥威力是和其他能力组合用,单独看只是个上传接口。
4.1 + Prompt Caching:长文档反复问答省 90%
文档内容 token 在第一次问答时全价计费,后续 5 分钟内的复用按 1/10 计价。
response = client.messages.create(
model="claude-opus-4-7",
max_tokens=4096,
extra_headers={"anthropic-beta": "files-api-2025-04-14"},
messages=[
{
"role": "user",
"content": [
{
"type": "document",
"source": {"type": "file", "file_id": file_id},
"cache_control": {"type": "ephemeral"},
},
{"type": "text", "text": "问题 1..."},
],
}
],
)
response = client.messages.create(
model="claude-opus-4-7",
max_tokens=4096,
extra_headers={"anthropic-beta": "files-api-2025-04-14"},
messages=[
{
"role": "user",
"content": [
{
"type": "document",
"source": {"type": "file", "file_id": file_id},
"cache_control": {"type": "ephemeral"},
},
{"type": "text", "text": "问题 1..."},
],
}
],
)
cache 5 分钟内反复命中,法务团队连续问 20 个问题,实际计费只有 1 次全价 + 19 次 1/10 价。
4.2 + Batch API:批量处理多份文档
Batch API 用于"我有 1000 份发票,半小时内出结果可以接受异步"这类场景,价格是同步接口的一半。Files API 上传的文件可以被 Batch 任务引用,1000 份发票实际只占 1000 个 file_id,不需要在请求里塞 base64。
import json
batch_requests = [
{
"custom_id": f"invoice_{i}",
"params": {
"model": "claude-haiku-4-5-20251001",
"max_tokens": 1024,
"messages": [{
"role": "user",
"content": [
{"type": "document", "source": {"type": "file", "file_id": fid}},
{"type": "text", "text": "抽取发票号、日期、金额,输出 JSON"},
],
}],
},
}
for i, fid in enumerate(invoice_file_ids)
]
batch = client.messages.batches.create(
requests=batch_requests,
extra_headers={"anthropic-beta": "files-api-2025-04-14,message-batches-2024-09-24"},
)
import json
batch_requests = [
{
"custom_id": f"invoice_{i}",
"params": {
"model": "claude-haiku-4-5-20251001",
"max_tokens": 1024,
"messages": [{
"role": "user",
"content": [
{"type": "document", "source": {"type": "file", "file_id": fid}},
{"type": "text", "text": "抽取发票号、日期、金额,输出 JSON"},
],
}],
},
}
for i, fid in enumerate(invoice_file_ids)
]
batch = client.messages.batches.create(
requests=batch_requests,
extra_headers={"anthropic-beta": "files-api-2025-04-14,message-batches-2024-09-24"},
)
4.3 + Code Execution Tool:把 CSV 喂进沙箱
Code Execution Tool 允许 Claude 在沙箱里跑 Python,适合分析 CSV / Excel。文件通过 Files API 上传后,用 container_upload 类型挂载到沙箱:
response = client.messages.create(
model="claude-opus-4-7",
max_tokens=4096,
tools=[{"type": "code_execution_20250522", "name": "code_execution"}],
extra_headers={
"anthropic-beta": "files-api-2025-04-14,code-execution-2025-05-22"
},
messages=[
{
"role": "user",
"content": [
{"type": "container_upload", "file_id": csv_file_id},
{"type": "text", "text": "分析销售数据,给出 Top 10 SKU 与同比增速。"},
],
}
],
)
response = client.messages.create(
model="claude-opus-4-7",
max_tokens=4096,
tools=[{"type": "code_execution_20250522", "name": "code_execution"}],
extra_headers={
"anthropic-beta": "files-api-2025-04-14,code-execution-2025-05-22"
},
messages=[
{
"role": "user",
"content": [
{"type": "container_upload", "file_id": csv_file_id},
{"type": "text", "text": "分析销售数据,给出 Top 10 SKU 与同比增速。"},
],
}
],
)
Claude 会在沙箱里 pd.read_csv() 这份文件,跑分析,输出结论。
4.4 + MCP / Managed Agents:跨会话共享文件
Managed Agents API(2026-04-01 beta)允许在 agent session 里 mount 文件——挂载产生的是"session 内的副本 file_id",不占用户存储配额,且 agent 不能修改原文件。这套机制让多个 agent 共享一份标准文档(比如客服 SOP)成为可能。
五、错误码与排查
| HTTP 码 | 错误类型 | 常见原因 | 处理 |
|---|---|---|---|
| 400 | invalid_request_error |
漏 beta header | 加 anthropic-beta: files-api-2025-04-14 |
| 400 | file_too_large_for_context |
文件比上下文窗口大 | 切分或换更大上下文模型 |
| 400 | invalid_filename |
文件名非法 | 限制在 1-255 字符,移除路径分隔符 |
| 413 | request_too_large |
文件 > 500 MB | 拆分或压缩 |
| 403 | storage_limit_exceeded |
组织达 100 GB | 清理旧文件,或加配额 |
| 404 | not_found |
file_id 已删除或拼错 | 校验 file_id 是否仍存在 |
六、5 条生产经验
经验 1:beta header 写在 SDK 初始化里,不要散落在每次调用
client = anthropic.Anthropic(
api_key="...",
base_url="https://gw.claudeapi.com",
default_headers={"anthropic-beta": "files-api-2025-04-14"},
)
client = anthropic.Anthropic(
api_key="...",
base_url="https://gw.claudeapi.com",
default_headers={"anthropic-beta": "files-api-2025-04-14"},
)
避免 90% 的 400 错误。
经验 2:file_id 不要直接暴露给前端
file_id 在同 workspace 内全局可引用,前端拿到等于拿到文件指针。前端应该用自己的业务 ID(如 doc_uuid)做映射,后端维护 doc_uuid → file_id 关系。
经验 3:scope 是 workspace,不是 API key
同一个 workspace 下,API key A 上传的文件,API key B 可以引用。这意味着工作流可以一个 key 专门做上传(权限受限),另一个 key 做问答。但也意味着多租户系统必须自己做隔离——不要把多个客户放在同一 workspace。
经验 4:删除是异步可见的,不要"删除后立即引用"做测试
DELETE 返回 200 不代表存储端立刻清理,极短时间内可能仍能引用。生产代码不要写这种边界用例的逻辑。
经验 5:用 created_at 而不是 updated_at
Files API 没有 updated_at——文件一旦上传就不可改,要改就重传。本地索引按 created_at 排序做 LRU 清理即可。
七、模型选型参考
Files API 本身和模型无关,但配合不同模型的常见组合:
| 场景 | 推荐模型 | 原因 |
|---|---|---|
| 大文档深度问答(合同/财报/论文) | Opus 4.7 | 推理深度高,长上下文稳 |
| 标准文档问答(产品手册/SOP) | Sonnet 4.6 | 性价比最高,大部分场景够用 |
| 批量结构化抽取(发票/简历/订单) | Haiku 4.5 | 极速,适合 Batch + Files 组合 |
| 数据分析(CSV/Excel + code execution) | Sonnet 4.6 / Opus 4.7 | 看分析复杂度选 |
小结
Files API 把"重复上传"这个朴素的浪费消灭掉,真正的工程价值在于和 Prompt Caching、Batch、Code Execution、Managed Agents 的组合——单独看它就是个上传接口,组合起来可以把生产环境的 token 成本和延迟降一个数量级。
接入要点就三句话:SDK 初始化时塞 beta header、本地用 SHA-256 做去重索引、按用途分类设清理策略。剩下都是细节。
国内开发者直接调用 Anthropic 官方 Files API 会被防火长城拦截,推荐通过 claudeapi.com 接入:base_url 改为 https://gw.claudeapi.com,SDK 一行不动,Files API 配额、上传速度、调用日志都能在 console.claudeapi.com 控制台看到。人民币结算,支持支付宝/微信充值与对公开票。



