🌐 Update translations for zh (add-missing) (#15175)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Sebastián Ramírez 2026-03-20 15:29:48 +01:00 committed by GitHub
parent b4f81b40a8
commit 5ef5490bc4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 522 additions and 0 deletions

View File

@ -0,0 +1,63 @@
# 在 JSON 中使用 Base64 表示字节 { #json-with-bytes-as-base64 }
如果你的应用需要接收和发送 JSON 数据,但其中需要包含二进制数据,可以将其编码为 base64。
## Base64 与文件 { #base64-vs-files }
请先考虑是否可以使用 [请求文件](../tutorial/request-files.md) 来上传二进制数据,并使用 [自定义响应 - FileResponse](./custom-response.md#fileresponse--fileresponse-) 来发送二进制数据,而不是把它编码进 JSON。
JSON 只能包含 UTF-8 编码的字符串,因此无法直接包含原始字节。
Base64 可以把二进制数据编码为字符串,但为此会使用比原始二进制更多的字符,因此通常比直接使用文件的效率更低。
仅当你确实需要在 JSON 中包含二进制数据且无法使用文件时,才使用 base64。
## Pydantic `bytes` { #pydantic-bytes }
你可以声明带有 `bytes` 字段的 Pydantic 模型,然后在模型配置中使用 `val_json_bytes` 指定用 base64 来验证输入的 JSON 数据;作为验证的一部分,它会将该 base64 字符串解码为字节。
{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *}
查看 `/docs` 时,你会看到字段 `data` 期望接收 base64 编码的字节:
<div class="screenshot">
<img src="/img/tutorial/json-base64-bytes/image01.png">
</div>
你可以发送如下请求:
```json
{
"description": "Some data",
"data": "aGVsbG8="
}
```
/// tip | 提示
`aGVsbG8=``hello` 的 base64 编码。
///
随后 Pydantic 会解码该 base64 字符串,并在模型的 `data` 字段中提供原始字节。
你将会收到类似的响应:
```json
{
"description": "Some data",
"content": "hello"
}
```
## 用于输出数据的 Pydantic `bytes` { #pydantic-bytes-for-output-data }
对于输出数据,你也可以在模型配置中为 `bytes` 字段使用 `ser_json_bytes`Pydantic 会在生成 JSON 响应时将字节以 base64 进行序列化。
{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *}
## 用于输入和输出数据的 Pydantic `bytes` { #pydantic-bytes-for-input-and-output-data }
当然,你也可以使用同一个配置了 base64 的模型,在接收和发送 JSON 数据时,同时处理输入(使用 `val_json_bytes` 进行验证)和输出(使用 `ser_json_bytes` 进行序列化)。
{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *}

View File

@ -0,0 +1,117 @@
# 流式数据 { #stream-data }
如果你要流式传输可以结构化为 JSON 的数据,你应该[流式传输 JSON Lines](../tutorial/stream-json-lines.md)。
但如果你想流式传输纯二进制数据或字符串,可以按下面的方法操作。
/// info | 信息
自 FastAPI 0.134.0 起新增。
///
## 使用场景 { #use-cases }
如果你想流式传输纯字符串,例如直接来自某个 AI LLM 服务的输出,可以使用它。
你也可以用它来流式传输大型二进制文件,在读取的同时按块发送,无需一次性把所有内容读入内存。
你还可以用这种方式流式传输视频或音频,甚至可以在处理的同时生成并发送。
## 使用 `yield``StreamingResponse` { #a-streamingresponse-with-yield }
如果你在*路径操作函数*中声明 `response_class=StreamingResponse`,你就可以使用 `yield` 依次发送每个数据块。
{* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *}
FastAPI 会将每个数据块原样交给 `StreamingResponse`,不会尝试将其转换为 JSON 或做类似处理。
### 非 async 的*路径操作函数* { #non-async-path-operation-functions }
你也可以使用常规的 `def` 函数(不带 `async`),并以相同方式使用 `yield`
{* ../../docs_src/stream_data/tutorial001_py310.py ln[26:29] hl[27] *}
### 无需注解 { #no-annotation }
你其实不需要为流式二进制数据声明返回类型注解。
由于 FastAPI 不会使用 Pydantic 将数据转换为 JSON也不会以任何方式序列化在这种情况下类型注解只供你的编辑器和工具使用FastAPI 不会使用它。
{* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *}
这也意味着,使用 `StreamingResponse` 时,你拥有按需精确生成与编码字节数据的自由,同时也承担相应的责任,它与类型注解无关。🤓
### 流式传输字节 { #stream-bytes }
主要的用例之一是流式传输 `bytes` 而不是字符串,这当然可以做到。
{* ../../docs_src/stream_data/tutorial001_py310.py ln[44:47] hl[47] *}
## 自定义 `PNGStreamingResponse` { #a-custom-pngstreamingresponse }
在上面的示例中,虽然按字节流式传输了数据,但响应没有 `Content-Type` 头,因此客户端不知道接收到的数据类型。
你可以创建 `StreamingResponse` 的自定义子类,将 `Content-Type` 头设置为你要流式传输的数据类型。
例如,你可以创建一个 `PNGStreamingResponse`,通过 `media_type` 属性把 `Content-Type` 头设置为 `image/png`
{* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *}
然后你可以在*路径操作函数*中通过 `response_class=PNGStreamingResponse` 使用这个新类:
{* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *}
### 模拟文件 { #simulate-a-file }
在这个示例中,我们用 `io.BytesIO` 模拟了一个文件,它是只驻留在内存中的类文件对象,但提供相同的接口。
例如,我们可以像对文件那样迭代它来消费其内容。
{* ../../docs_src/stream_data/tutorial002_py310.py ln[1:27] hl[3,12:13,25] *}
/// note | 技术细节
另外两个变量 `image_base64``binary_image` 表示一张图像,先用 Base64 编码,再转换为 bytes最后传给 `io.BytesIO`
只是为了让它们能和示例放在同一个文件里,便于你直接复制运行。🥚
///
通过使用 `with` 代码块,我们确保在生成器函数(带有 `yield` 的函数)完成后关闭这个类文件对象。也就是在发送完响应之后。
在这个特定示例中这并不那么重要,因为它是一个内存中的假文件(使用 `io.BytesIO`),但对于真实文件,确保在完成相关工作后关闭文件是很重要的。
### 文件与异步 { #files-and-async }
大多数情况下,类文件对象默认与 async 和 await 不兼容。
例如,它们没有 `await file.read()`,也不支持 `async for chunk in file`
而且很多情况下,读取它们是一个阻塞操作(可能会阻塞事件循环),因为数据来自磁盘或网络。
/// info | 信息
上面的示例其实是个例外,因为 `io.BytesIO` 对象已经在内存中,所以读取它不会阻塞。
但在许多情况下,读取文件或类文件对象会发生阻塞。
///
为避免阻塞事件循环,你可以简单地把*路径操作函数*声明为常规的 `def`(而不是 `async def`),这样 FastAPI 会在一个线程池工作线程上运行它,从而避免阻塞主事件循环。
{* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *}
/// tip | 提示
如果你需要在异步函数里调用阻塞代码,或在阻塞函数里调用异步函数,可以使用 [Asyncer](https://asyncer.tiangolo.com),它是 FastAPI 的姐妹库。
///
### `yield from` { #yield-from }
当你在迭代某个对象(例如类文件对象),并为每个条目执行 `yield` 时,你也可以使用 `yield from` 直接产出每个条目,从而省去 `for` 循环。
这并不是 FastAPI 特有的功能,只是 Python 的语法,但这是一个值得知道的小技巧。😎
{* ../../docs_src/stream_data/tutorial002_py310.py ln[37:40] hl[40] *}

View File

@ -0,0 +1,88 @@
# 严格的 Content-Type 检查 { #strict-content-type-checking }
默认情况下FastAPI 对 JSON 请求体使用严格的 `Content-Type` 头检查。这意味着JSON 请求必须包含有效的 `Content-Type` 头(例如 `application/json`),其请求体才会被按 JSON 解析。
## CSRF 风险 { #csrf-risk }
此默认行为在一个非常特定的场景下可防御一类跨站请求伪造CSRF攻击。
这类攻击利用了浏览器的一个事实:当请求满足以下条件时,浏览器允许脚本在不进行任何 CORS 预检的情况下直接发送请求:
- 没有 `Content-Type` 头(例如使用 `fetch()` 携带 `Blob` 作为 body
- 且不发送任何认证凭据。
这种攻击主要在以下情况下相关:
- 应用在本地(如 `localhost`)或内网中运行
- 且应用没有任何认证,假定来自同一网络的请求都可信。
## 攻击示例 { #example-attack }
假设你构建了一个本地运行的 AI 代理。
它提供了一个 API地址为
```
http://localhost:8000/v1/agents/multivac
```
另有一个前端,地址为
```
http://localhost:8000
```
/// tip | 提示
注意它们的主机相同。
///
之后,你可以通过前端让该 AI 代理替你执行操作。
由于它在本地运行、而非暴露在开放的互联网,你决定不配置任何认证,只信任对本地网络的访问。
于是,你的某位用户安装并在本地运行了它。
然后他(她)可能会打开一个恶意网站,例如
```
https://evilhackers.example.com
```
该恶意网站使用 `fetch()` 携带 `Blob` 作为 body向本地 API 发送请求,地址为
```
http://localhost:8000/v1/agents/multivac
```
尽管恶意网站与本地应用的主机不同,浏览器仍不会触发 CORS 预检请求,原因是:
- 请求不涉及任何认证,无需发送凭据。
- 浏览器认为它并未发送 JSON因为缺少 `Content-Type` 头)。
于是,该恶意网站就可能让本地 AI 代理替用户向前老板发送愤怒消息……甚至更糟。😅
## 开放的互联网 { #open-internet }
如果你的应用部署在开放的互联网,你不会“信任网络”,也不会允许任何人不经认证就发送特权请求。
攻击者完全可以直接运行脚本向你的 API 发送请求,无需借助浏览器交互,因此你很可能已经对任何特权端点做好了安全防护。
在这种情况下,以上攻击/风险不适用于你。
该风险/攻击主要发生在应用运行于本地网络、且“仅依赖网络隔离作为保护”的场景。
## 允许无 Content-Type 的请求 { #allowing-requests-without-content-type }
如果你需要兼容不发送 `Content-Type` 头的客户端,可以通过设置 `strict_content_type=False` 来关闭严格检查:
{* ../../docs_src/strict_content_type/tutorial001_py310.py hl[4] *}
启用该设置后,缺少 `Content-Type` 头的请求其请求体也会按 JSON 解析,这与旧版本 FastAPI 的行为一致。
/// info | 信息
此行为和配置在 FastAPI 0.132.0 中新增。
///

View File

@ -0,0 +1,23 @@
# 编辑器支持 { #editor-support }
官方的 [FastAPI 扩展](https://marketplace.visualstudio.com/items?itemName=FastAPILabs.fastapi-vscode)为你的 FastAPI 开发流程带来增强,包括*路径操作*的发现与导航、部署到 FastAPI Cloud以及实时日志流式传输。
有关该扩展的更多详情,请参阅其 [GitHub 仓库](https://github.com/fastapi/fastapi-vscode)中的 README。
## 安装与配置 { #setup-and-installation }
**FastAPI 扩展**同时适用于 [VS Code](https://code.visualstudio.com/) 和 [Cursor](https://www.cursor.com/)。你可以在各编辑器的扩展面板中直接搜索 “FastAPI”并选择由 **FastAPI Labs** 发布的扩展进行安装。该扩展也适用于基于浏览器的编辑器,例如 [vscode.dev](https://vscode.dev) 和 [github.dev](https://github.dev)。
### 应用发现 { #application-discovery }
默认情况下,扩展会通过扫描实例化了 `FastAPI()` 的文件,自动发现工作区中的 FastAPI 应用。如果你的项目结构无法自动检测,你可以通过 `pyproject.toml` 中的 `[tool.fastapi]` 或 VS Code 设置项 `fastapi.entryPoint` 来指定入口点,使用模块表示法(例如 `myapp.main:app`)。
## 功能 { #features }
- **Path Operation 资源管理器** - 侧边栏树状视图展示应用中的所有 <dfn title="路由,端点">*路径操作*</dfn>。点击可跳转至任一路由或 APIRouter 的定义。
- **路由搜索** - 使用 <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>E</kbd>macOS 上为 <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>E</kbd>)按路径、方法或名称进行搜索。
- **CodeLens 导航** - 测试客户端调用(例如 `client.get('/items')`)上方的可点击链接,可跳转到匹配的*路径操作*,在测试与实现之间快速往返。
- **部署到 FastAPI Cloud** - 一键将你的应用部署到 [FastAPI Cloud](https://fastapicloud.com/)。
- **应用日志流式传输** - 从部署在 FastAPI Cloud 的应用中实时流式获取日志,并支持按级别过滤与文本搜索。
如果你想先熟悉扩展功能,可以打开命令面板(<kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd>macOS 上为 <kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>P</kbd>),选择 “Welcome: Open walkthrough...”,然后选择 “Get started with FastAPI” 演练。

View File

@ -0,0 +1,120 @@
# 服务器发送事件SSE { #server-sent-events-sse }
你可以使用**服务器发送事件**SSE向客户端流式发送数据。
这类似于[流式传输 JSON Lines](stream-json-lines.md),但使用 `text/event-stream` 格式,浏览器原生通过 [`EventSource` API](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) 支持。
/// info | 信息
新增于 FastAPI 0.135.0。
///
## 什么是服务器发送事件? { #what-are-server-sent-events }
SSE 是一种通过 HTTP 从服务器向客户端流式传输数据的标准。
每个事件是一个带有 `data`、`event`、`id` 和 `retry` 等“字段”的小文本块,以空行分隔。
看起来像这样:
```
data: {"name": "Portal Gun", "price": 999.99}
data: {"name": "Plumbus", "price": 32.99}
```
SSE 常用于 AI 聊天流式输出、实时通知、日志与可观测性,以及其他服务器向客户端推送更新的场景。
/// tip | 提示
如果你想流式传输二进制数据(例如视频或音频),请查看高级指南:[流式传输数据](../advanced/stream-data.md)。
///
## 使用 FastAPI 流式传输 SSE { #stream-sse-with-fastapi }
要在 FastAPI 中流式传输 SSE在你的*路径操作函数*中使用 `yield`,并设置 `response_class=EventSourceResponse`
`fastapi.sse` 导入 `EventSourceResponse`
{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[1:25] hl[4,22] *}
每个被 yield 的项会被编码为 JSON并放入 SSE 事件的 `data:` 字段发送。
如果你将返回类型声明为 `AsyncIterable[Item]`FastAPI 将使用它通过 Pydantic对数据进行**校验**、**文档化**和**序列化**。
{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[1:25] hl[10:12,23] *}
/// tip | 提示
由于 Pydantic 会在**Rust** 端序列化它,相比未声明返回类型,你将获得更高的**性能**。
///
### 非 async 的*路径操作函数* { #non-async-path-operation-functions }
你也可以使用常规的 `def` 函数(没有 `async`),并以同样的方式使用 `yield`
FastAPI 会确保其正确运行,从而不阻塞事件循环。
由于此时函数不是 async正确的返回类型应为 `Iterable[Item]`
{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[28:31] hl[29] *}
### 无返回类型 { #no-return-type }
你也可以省略返回类型。FastAPI 将使用 [`jsonable_encoder`](./encoder.md) 转换数据并发送。
{* ../../docs_src/server_sent_events/tutorial001_py310.py ln[34:37] hl[35] *}
## `ServerSentEvent` { #serversentevent }
如果你需要设置 `event`、`id`、`retry` 或 `comment` 等 SSE 字段,你可以 yield `ServerSentEvent` 对象,而不是直接返回数据。
`fastapi.sse` 导入 `ServerSentEvent`
{* ../../docs_src/server_sent_events/tutorial002_py310.py hl[4,26] *}
`data` 字段始终会被编码为 JSON。你可以传入任何可被序列化为 JSON 的值,包括 Pydantic 模型。
## 原始数据 { #raw-data }
如果你需要发送**不**进行 JSON 编码的数据,请使用 `raw_data` 而不是 `data`
这对于发送预格式化文本、日志行或特殊的 <dfn title="用于指示特殊条件或状态的值">"哨兵"</dfn> 值(例如 `[DONE]`)很有用。
{* ../../docs_src/server_sent_events/tutorial003_py310.py hl[17] *}
/// note | 注意
`data``raw_data` 是互斥的。每个 `ServerSentEvent` 上只能设置其中一个。
///
## 使用 `Last-Event-ID` 恢复 { #resuming-with-last-event-id }
当连接中断后浏览器重新连接时,会在 `Last-Event-ID` 头中发送上次收到的 `id`
你可以将其读取为一个请求头参数,并据此从客户端离开的地方恢复流:
{* ../../docs_src/server_sent_events/tutorial004_py310.py hl[25,27,31] *}
## 使用 POST 的 SSE { #sse-with-post }
SSE 适用于**任意 HTTP 方法**,不仅仅是 `GET`
这对像 [MCP](https://modelcontextprotocol.io) 这样通过 `POST` 传输 SSE 的协议很有用:
{* ../../docs_src/server_sent_events/tutorial005_py310.py hl[14] *}
## 技术细节 { #technical-details }
FastAPI 开箱即用地实现了一些 SSE 的最佳实践。
- 当 15 秒内没有任何消息时,发送一个**保活 `ping` 注释**,以防某些代理关闭连接,正如 [HTML 规范Server-Sent Events](https://html.spec.whatwg.org/multipage/server-sent-events.html#authoring-notes) 中建议的那样。
- 设置 `Cache-Control: no-cache` 响应头,**防止缓存**流。
- 设置特殊响应头 `X-Accel-Buffering: no`,以**防止**某些代理(如 Nginx**缓冲**。
你无需做任何事,它开箱即用。🤓

View File

@ -0,0 +1,111 @@
# 流式传输 JSON Lines { #stream-json-lines }
当你想以“流”的方式发送一系列数据时,可以使用 JSON Lines。
/// info | 信息
新增于 FastAPI 0.134.0。
///
## 什么是流 { #what-is-a-stream }
“流式传输”数据意味着你的应用会在整段数据全部准备好之前,就开始把每个数据项发送给客户端。
也就是说,它会先发送第一个数据项,客户端会接收并开始处理它,而此时你的应用可能还在生成下一个数据项。
```mermaid
sequenceDiagram
participant App
participant Client
App->>App: Produce Item 1
App->>Client: Send Item 1
App->>App: Produce Item 2
Client->>Client: Process Item 1
App->>Client: Send Item 2
App->>App: Produce Item 3
Client->>Client: Process Item 2
App->>Client: Send Item 3
Client->>Client: Process Item 3
Note over App: Keeps producing...
Note over Client: Keeps consuming...
```
它甚至可以是一个无限流,你可以一直持续发送数据。
## JSON Lines { #json-lines }
在这些场景中,常见的做法是发送 “JSON Lines”这是一种每行发送一个 JSON 对象的格式。
响应的内容类型是 `application/jsonl`(而不是 `application/json`),响应体类似这样:
```json
{"name": "Plumbus", "description": "A multi-purpose household device."}
{"name": "Portal Gun", "description": "A portal opening device."}
{"name": "Meeseeks Box", "description": "A box that summons a Meeseeks."}
```
它与 JSON 数组(相当于 Python 的 list非常相似但不是用 `[]` 包裹、并在各项之间使用 `,` 分隔,而是每行一个 JSON 对象,彼此以换行符分隔。
/// info | 信息
关键在于你的应用可以逐行生成数据,而客户端在消费前面的行。
///
/// note | 技术细节
由于每个 JSON 对象将以换行分隔,它们的内容中不能包含字面量换行符,但可以包含转义换行符(`\n`),这属于 JSON 标准的一部分。
不过通常你无需操心,这些都会自动完成,继续阅读即可。🤓
///
## 使用场景 { #use-cases }
你可以用它来从 AI LLM 服务、日志或遥测中流式传输数据,或其他可以用 JSON 项目来结构化的数据。
/// tip | 提示
如果你想流式传输二进制数据,例如视频或音频,请查看进阶指南:[流式传输数据](../advanced/stream-data.md)。
///
## 使用 FastAPI 流式传输 JSON Lines { #stream-json-lines-with-fastapi }
要在 FastAPI 中流式传输 JSON Lines可以在路径操作函数中不用 `return`,而是用 `yield` 逐个产生每个数据项。
{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[1:24] hl[24] *}
如果你要返回的每个 JSON 项是类型 `Item`(一个 Pydantic 模型),并且这是一个异步函数,你可以将返回类型声明为 `AsyncIterable[Item]`
{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[1:24] hl[9:11,22] *}
如果你声明了返回类型FastAPI 会用它来验证数据、在 OpenAPI 中生成文档、进行过滤,并使用 Pydantic 进行序列化。
/// tip | 提示
由于 Pydantic 会在 Rust 侧进行序列化,如果你声明了返回类型,将获得更高的性能。
///
### 非异步的*路径操作函数* { #non-async-path-operation-functions }
你也可以使用常规的 `def` 函数(不带 `async`),并以同样的方式使用 `yield`
FastAPI 会确保其正确运行,不会阻塞事件循环。
因为这个函数不是异步的,合适的返回类型是 `Iterable[Item]`
{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[27:30] hl[28] *}
### 无返回类型 { #no-return-type }
你也可以省略返回类型。此时 FastAPI 会使用 [`jsonable_encoder`](./encoder.md) 将数据转换为可序列化为 JSON 的形式,然后以 JSON Lines 发送。
{* ../../docs_src/stream_json_lines/tutorial001_py310.py ln[33:36] hl[34] *}
## 服务器发送事件SSE { #server-sent-events-sse }
FastAPI 还对 Server-Sent EventsSSE提供一等支持它们与此非常相似但有一些额外细节。你可以在下一章了解更多[服务器发送事件SSE](server-sent-events.md)。🤓