Gemini 文件输入走 inline 还是 Files API
Gemini 的文件输入按请求总体积分流:总请求超过 100 MB(PDF 超过 50 MB)就该用 Files API,其余可内联;Files API 文件保留 48 小时。(核验 2026-11-05,F103、F104)
一、Gemini 文件输入走 inline 还是 Files API:问题不在文件多大,而在请求多大
「多大的文件该用 Files API?」这个问题问得不精确,所以答案总在变。有人记成 20 MB,有人记成 50 MB,还有人干脆一律上传。
官方的口径是按总请求大小算的:把文件、提示词、系统指令加在一起,超过 100 MB 就该用 Files API;PDF 的门槛更低,是 50 MB(F103)。注意主语是「总请求」,不是「单个文件」——一个 90 MB 的视频配上两万字的系统指令,总量可能就过了线。
这个区别不是文字游戏。内联(inline)是把二进制塞进请求体,网关、日志、代理都要过一遍;超限的失败往往发生在你还没看到 API 报错之前,表现成「请求发不出去」或者「被截断」,排查起来比一个明确的状态码更费时间。
二、Gemini 文件输入选择:最小可运行示例
把「文件类型 + 体积」丢进一个函数,决策就能复算。
## EXPECT: image 3MB → inline | pdf 55MB → files_api | video 95MB → inline | 门槛:总请求 100 MB,PDF 50 MB
INLINE_LIMIT_MB = 100
PDF_LIMIT_MB = 50
CASES = [("image", 3), ("pdf", 55), ("video", 95)]
def choose(kind, size_mb, prompt_mb=1):
# prompt_mb:提示词与系统指令的估算体积(MB)。纯文本通常远小于 1,
# 这里默认 1 只是留余量;真实值请按你的系统指令长度填。
total = size_mb + prompt_mb
limit = PDF_LIMIT_MB if kind == "pdf" else INLINE_LIMIT_MB
return "files_api" if total > limit else "inline"
decisions = [(kind, size, choose(kind, size)) for kind, size in CASES]
assert decisions[0][2] == "inline"
assert decisions[1][2] == "files_api"
assert decisions[2][2] == "inline"
print(" | ".join(f"{kind} {size}MB → {tool}" for kind, size, tool in decisions) +
f" | 门槛:总请求 {INLINE_LIMIT_MB} MB,PDF {PDF_LIMIT_MB} MB")
prompt_mb 这个参数容易被忽略:它是提示词与系统指令的体积,纯文本一般远小于 1 MB,但长系统指令加上少样本示例,攒到几百 KB 很常见,够把 95 MB 推到线外。结果里还有一处反直觉:55 MB 的 PDF 必须上传,而 95 MB 的视频反而可以内联。原因就是两条门槛不同——PDF 按 50 MB 卡,其他类型按 100 MB 卡。如果你只记住「大文件上传」,这一条会一直踩。
三、解释与边界:上传之后还有三个约束
第一个,文件有寿命。 Files API 保留文件 48 小时,之后自动删除,也可以手动删(F104)。这意味着「上传一次、长期引用那个 uri」不成立:第二天再拿旧的 uri 去请求,会失败。要么在请求前重新上传,要么在业务侧维护「uri 有效期」,快到期就续。
第二个,配额是项目级的。 每个项目最多存 20 GB,单文件最大 2 GB(F104)。批量处理时这个配额会先满,而不是单文件超限——尤其是视频,一个几十分钟的素材就占掉几百 MB。清理策略要跟着上传频率走,别等满了再删。
第三个,传上去的东西拿不回来。 用户上传的文件不能下载,只有模型生成的文件(比如视频)可以(F104)。所以「原件留档」这件事必须自己做,别把 Files API 当成存储用。
什么时候仍然该用内联? 小文件、一次性请求、以及对延迟敏感的场景。内联少一次上传往返,也不用管过期。判据很简单:这个文件会不会在多个请求里复用?会,就上传;不会,且体积在门槛内,就内联。
上传之后的调用形态值得单独说一句。 Files API 返回的是文件引用(uri 加 mime_type),后续请求把这两个值放进内容项里即可。官方示例里的写法是把内容项写成 {"type": "image", "uri": ..., "mime_type": ...} 这种结构——注意它和文本项是同级的,可以混在同一个 input 数组里。这意味着「一张图 + 一段话」不需要拼成什么特殊格式,就是数组里的两个元素。
内联适合四类场景。 一是小文件,体积远低于门槛;二是一次性请求,传完就不再用;三是延迟敏感,少一次上传往返;四是调试阶段,省掉「上传—取 uri—再发请求」两步。反过来说,只要出现「同一份文件要给多个请求用」,就该上传——不是因为大,而是因为重复。
排查顺序也要定下来。 请求发不出去时,先量总请求体积(含提示词与系统指令),再确认 PDF 是否过了 50 MB 这条更低的线,最后才看是不是网关或代理的限制。前两步你自己能查,第三步要找人——顺序反了,会在别人那里绕一圈才回到原点。
配额要按缓存治理,不能按存储治理。 项目 20 GB 听起来够用,实际很容易满:一段十分钟的高清视频就可能占掉几百 MB,批量任务一天跑几十条,两天就顶到上限。可操作的做法是「用完就删」,或者按天跑一次清理。别指望 48 小时自动过期来兜底——在过期之前,你可能已经撞上配额了。
两个容易混的数字。 一是把「项目 20 GB」当成单文件上限——单文件是 2 GB,项目才是 20 GB,两者差一个数量级,搞混了会在单文件上传时莫名其妙失败。二是把「保留 48 小时」理解成「至少保留 48 小时」——官方的意思是 48 小时后删除,没有承诺提前不删,所以别把关键链路的可用性押在这个窗口的最后几分钟上。把这两个数字写进团队文档,比放在某个人的记忆里可靠。
门槛会变,别写死在代码里。 这两条数字来自官方文档,属于会随版本调整的参数。把它们放进配置而不是散落在判断语句里,调整时只改一处;顺手加一行启动日志把当前门槛打出来,下次排查会省一步。
边界。 本节只解决「走哪条路」。文件传上去之后怎么算 token,见 8.2、见 8.3;多模态提示词怎么写才有效,属于提示词质量,不在本节。Files API 本身免费(F104),成本发生在 token 上,别把两者混着算。
四、预期输出与异常分支
真跑输出:
image 3MB → inline | pdf 55MB → files_api | video 95MB → inline | 门槛:总请求 100 MB,PDF 50 MB
六类分支。把 55 MB 的 PDF 内联发出去:请求体过大,失败点可能在网关层,日志里看不到 API 的错误结构。只算文件大小、忘了提示词:90 MB 的文件配长提示词就过线了,prompt_mb 这个参数就是为这件事留的。上传后隔天才用:文件已过期(F104),报错信息通常只说文件不存在,不会提醒你 48 小时规则。项目配额满了:表现为上传失败,但根因是历史文件没清,不是网络问题。想下载用户上传的原件:不支持(F104),要么当初就自己留一份。文件名带中文或空格:上传接口一般能处理,但如果你的代码自己拼 multipart,注意别在编码上出错。
五、判据卡:多大该走 Files API
| 该这么做 | 不该这么做 |
|---|---|
| 按总请求体积判断,PDF 单列 50 MB | 只记「超过多少 MB 就上传」 |
| 复用的文件上传一次,记好有效期 | 上传后长期引用同一个 uri |
| 定期清理项目里的历史文件 | 等配额满了再处理 |
| 原件自己留档 | 把 Files API 当存储用 |
六、来源与核验
https://aistudio.google.com/docs/files.md(核验 2026-11-05,F103、F104)
门槛与配额属于「API 结构」档事实,复核周期三个月,见 1.3。若官方调整 100 MB/50 MB 这两个阈值,本节的决策函数要整段重算,不能只改注释。
七、动手试
- 把
CASES里 PDF 的体积改成45,重跑。预期它变成inline;验收标准是你能说清「45 MB 的 PDF 为什么可以内联,而 55 MB 的不行」。 - 把
prompt_mb的默认值改成10,重跑。预期video 95MB从inline变成files_api;验收标准是说明「提示词也算进请求体积」这件事在真实系统里怎么踩到。 - 打开你项目里上传文件的那段代码,看它有没有处理「48 小时后过期」。验收标准:能指出续期的判断写在哪一行;找不到,就说明这条路径目前是「上传一次用到底」。

TRAE-AI编程


更多建议: