ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

FastAPI流式输出实战:从基础StreamingResponse到SSE实时推送

FastAPI流式输出实战:从基础StreamingResponse到SSE实时推送 在实际 Web 开发中尤其是构建实时数据推送、大文件处理、AI 对话或日志流式查看等场景时传统的“请求-响应”模式会阻塞客户端直到服务器生成完整响应。这不仅导致前端长时间等待用户体验不佳还可能因超时导致请求失败。FastAPI 作为高性能的 Python Web 框架原生支持多种流式输出方案能够高效地将数据分块、实时地推送给客户端实现类似“打字机”或“进度条”的效果。本文将围绕 FastAPI 实现流式输出的核心机制展开涵盖从基础概念到生产级应用的全过程。无论你是需要为前端提供实时日志流还是构建一个类似 ChatGPT 的逐字输出对话接口或是处理大型文件的流式下载都能在本文中找到对应的实现路径和避坑指南。我们将从最基础的StreamingResponse开始逐步深入到更适用于实时事件流的 Server-Sent Events (SSE)并解释其背后的原理、配置要点以及如何与前端如 Vue.js或后端如 Java 的 RestTemplate进行联调。读完本文你将能够独立设计并部署一个健壮的 FastAPI 流式输出服务。1. 理解 FastAPI 流式输出的核心机制与选型在动手写代码之前必须先弄清楚 FastAPI 支持哪些流式输出方式以及它们各自适合什么场景。选型错误会导致后续开发事倍功半甚至无法满足需求。1.1 什么是流式输出通俗地讲流式输出就是服务器不一次性生成所有数据并返回而是像打开一个水龙头数据分成许多小块chunks一块一块地、持续不断地发送给客户端。客户端在收到第一块数据时就可以开始处理无需等待所有数据就绪。在技术定义上HTTP/1.1 协议通过Transfer-Encoding: chunked头部来支持分块传输编码。FastAPI 则提供了更上层的抽象让开发者可以方便地生成和发送这些数据块。1.2 FastAPI 的三种主流流式输出方式FastAPI 主要支持三种方式实现流式输出它们底层机制不同适用场景也各异。方式核心组件协议支持适用场景前端对接方式普通流式响应StreamingResponseHTTP/1.1 Chunked文件下载、大文本流、自定义二进制流Fetch API, Axios (处理response.body流)服务器发送事件StreamingResponse 特定格式HTTP/1.1 Chunked (SSE 规范)实时通知、聊天消息、股票行情、日志推送EventSourceAPI 或 Fetch APIWebSocketWebSocketWebSocket (ws:// 或 wss://)全双工实时通信如在线游戏、协作编辑WebSocket对象对于大多数“服务器主动向客户端推送数据”的场景如聊天AI逐字输出、实时日志Server-Sent Events (SSE)通常是更合适的选择。它基于简单的 HTTP 协议自动处理连接管理和重连前端使用标准的EventSourceAPI非常简单。而 WebSocket 更适用于需要客户端和服务器频繁双向通信的场景。本文重点讲解前两种基于 HTTP 的流式输出因为它们是构建 RESTful 流式接口的基石。理解了它们WebSocket 的实现也会触类旁通。1.3 流式输出背后的技术原理生成器与异步迭代FastAPI 流式输出的核心是 Python 的生成器或异步生成器。生成器函数使用yield关键字可以暂停执行并返回一个值下次从暂停处继续执行。这完美契合了“分批产生数据”的需求。一个同步生成器示例def simple_generator(): for i in range(5): # 模拟一些耗时操作 time.sleep(0.5) yield f数据块 {i}\n在 FastAPI 中我们将这样的生成器传递给StreamingResponse框架会自动以分块编码的形式将每个yield出的值发送给客户端。对于 I/O 密集型操作如从数据库或网络异步读取数据使用异步生成器(async def配合yield) 能极大提升并发性能这是 FastAPI 的优势所在。2. 环境准备与基础项目搭建在开始流式输出开发前需要一个干净的 Python 环境和一个最小化的 FastAPI 项目结构。这里我们使用当前主流的环境管理工具。2.1 创建虚拟环境与安装依赖强烈建议为每个项目创建独立的虚拟环境以避免包版本冲突。# 1. 创建项目目录并进入 mkdir fastapi-streaming-demo cd fastapi-streaming-demo # 2. 创建 Python 虚拟环境 (这里使用 Python 3.8) python -m venv venv # 3. 激活虚拟环境 # Windows: venv\Scripts\activate # Linux/macOS: source venv/bin/activate # 4. 升级 pip pip install --upgrade pip # 5. 安装核心依赖 pip install fastapi uvicornfastapi是框架本身uvicorn是 ASGI 服务器用于运行 FastAPI 应用。这是最基础的依赖。2.2 验证基础环境与第一个 API创建一个名为main.py的文件写入以下内容from fastapi import FastAPI import uvicorn app FastAPI(title流式输出演示) app.get(/) async def root(): return {message: FastAPI 流式输出服务已启动} if __name__ __main__: uvicorn.run(app, host0.0.0.0, port8000)运行应用python main.py访问http://localhost:8000或http://localhost:8000/docs你应该能看到 JSON 响应和自动生成的 API 文档。这确认了基础环境工作正常。2.3 项目结构建议对于稍复杂的流式输出项目建议采用以下结构将路由、业务逻辑和响应模型分离。fastapi-streaming-demo/ ├── venv/ # 虚拟环境目录.gitignore ├── main.py # 应用入口和路由注册 ├── core/ # 核心配置 │ └── config.py ├── routers/ # 路由模块 │ ├── __init__.py │ ├── stream_basic.py # 基础流式响应路由 │ └── sse.py # SSE 路由 ├── services/ # 业务逻辑服务 │ └── stream_service.py └── requirements.txt # 依赖列表现在将main.py重构为应用入口并创建第一个流式路由模块。3. 实现基础流式响应 (StreamingResponse)StreamingResponse是 FastAPI 中处理流式数据的通用容器。它接受一个异步生成器或普通生成器作为内容并将其以流的形式返回给客户端。3.1 创建第一个流式下载接口在routers/stream_basic.py中创建路由from fastapi import APIRouter from fastapi.responses import StreamingResponse import asyncio import time router APIRouter(prefix/stream/basic, tags[基础流式输出]) router.get(/text-stream) async def text_stream(): 流式输出文本数据模拟逐行读取大文件或生成长文本。 async def data_generator(): # 这是一个异步生成器 for i in range(1, 11): # 模拟每行数据生成的耗时 await asyncio.sleep(0.5) # 必须 yield 字符串或字节。注意格式这里每行加换行。 yield f这是第 {i} 行数据当前时间{time.strftime(%H:%M:%S)}\n # 将异步生成器包装成 StreamingResponse # media_type 可以设置为 text/plain, text/html, application/json 等 return StreamingResponse( contentdata_generator(), media_typetext/plain; charsetutf-8 )在main.py中注册这个路由from fastapi import FastAPI from routers import stream_basic, sse # 稍后创建 sse 模块 import uvicorn app FastAPI(title流式输出演示) app.include_router(stream_basic.router) # app.include_router(sse.router) # 稍后取消注释 app.get(/) async def root(): return {message: FastAPI 流式输出服务已启动} if __name__ __main__: uvicorn.run(app, host0.0.0.0, port8000)3.2 运行与测试启动服务后使用curl命令测试流式接口curl -N http://localhost:8000/stream/basic/text-stream参数-N表示禁用缓冲你会看到数据每隔 0.5 秒输出一行而不是等待 5 秒后一次性输出所有内容。这就是流式响应的效果。3.3 关键参数详解与常见配置StreamingResponse有几个关键参数需要理解参数类型默认值说明content异步迭代器/生成器必填数据源。可以是async for循环中的async生成器也可以是普通生成器。media_typestrNone设置Content-Type响应头。对于 SSE必须设为text/event-stream。对于普通文本建议设为text/plain; charsetutf-8。headersdictNone自定义响应头。常用于 SSE 设置Cache-Control: no-cache等。status_codeint200HTTP 状态码。一个更完整的配置示例from fastapi.responses import StreamingResponse import asyncio async def my_generator(): for i in range(5): await asyncio.sleep(1) yield fdata:{i}\n\n # 注意这是 SSE 格式后面会讲 response StreamingResponse( contentmy_generator(), media_typetext/event-stream, # 关键声明为 SSE headers{ Cache-Control: no-cache, Connection: keep-alive, # 保持连接对于长流很重要 X-Accel-Buffering: no, # 禁用 Nginx 等代理的缓冲 } )注意StreamingResponse默认会启用分块传输编码。如果你在 Nginx 或 Apache 后面部署可能需要额外配置来禁用代理缓冲否则数据可能不会实时推送到客户端。4. 实现 Server-Sent Events (SSE) 流式输出SSE 是一种允许服务器向客户端单向推送事件的 Web 技术。它基于 HTTP 长连接使用一个简单的文本格式。对于需要服务器主动推送、但不需要双向通信的场景如新闻推送、聊天机器人回复、任务进度SSE 比 WebSocket 更简单、更轻量。4.1 SSE 数据格式规范SSE 流中的每个事件由多行文本组成以两个换行符\n\n结束。核心字段有data: 事件的数据内容。如果数据有多行每行前面都要加data:。event: 事件类型前端可以根据此字段区分不同事件。id: 事件 ID用于断线重连时指定Last-Event-ID。retry: 重连时间毫秒。一个标准的 SSE 响应体看起来像这样event: message data: 这是第一条消息 data: 这是第二条消息 data: 它有两行 id: 123 event: close data: 连接关闭4.2 创建 SSE 流式接口在routers/sse.py中创建路由from fastapi import APIRouter, Request from fastapi.responses import StreamingResponse import asyncio import json import time router APIRouter(prefix/sse, tags[服务器发送事件(SSE)]) router.get(/chat-stream) async def chat_stream(request: Request, question: str 你好): 模拟 AI 聊天对话的逐字输出 (SSE 格式)。 :param question: 用户的问题 async def event_generator(): # 模拟 AI 思考并生成回复的过程 reply f你好你问的是{question}。这是一个模拟的流式回复 words list(reply) # 发送一个开始事件 yield fevent: start\ndata: 开始生成回复...\n\n # 逐字输出 for i, word in enumerate(words): # 检查客户端是否已断开连接 (对于长时间连接很重要) if await request.is_disconnected(): print(客户端断开连接) break await asyncio.sleep(0.1) # 模拟每个字生成需要时间 # 发送消息事件数据为 JSON 格式 event_data json.dumps({ word: word, index: i, is_end: False }, ensure_asciiFalse) yield fevent: message\ndata: {event_data}\n\n # 发送结束事件 yield fevent: end\ndata: 回复生成完毕\n\n return StreamingResponse( contentevent_generator(), media_typetext/event-stream, # 必须设置为 SSE 的 MIME 类型 headers{ Cache-Control: no-cache, Connection: keep-alive, X-Accel-Buffering: no, # 禁用 Nginx 缓冲 } )在main.py中注册此路由取消之前注释掉的行。4.3 使用 EventSource API 在前端接收 SSE创建一个简单的test_sse.html文件来测试!DOCTYPE html html head titleSSE 测试页面/title /head body h2SSE 聊天流测试/h2 input typetext idquestion valueFastAPI 是什么 / button onclickstartSSE()开始流式对话/button button onclickcloseSSE()停止接收/button hr div idoutput stylewhite-space: pre-wrap; border:1px solid #ccc; padding:10px; min-height:200px;/div script let eventSource null; function startSSE() { const question document.getElementById(question).value; const outputDiv document.getElementById(output); outputDiv.innerHTML ; // 清空之前的内容 // 构建 SSE 连接 URL const url http://localhost:8000/sse/chat-stream?question${encodeURIComponent(question)}; // 使用 EventSource API 连接 SSE 端点 eventSource new EventSource(url); // 监听自定义的 start 事件 eventSource.addEventListener(start, function(event) { outputDiv.innerHTML [系统] ${event.data}\n; }); // 监听自定义的 message 事件 eventSource.addEventListener(message, function(event) { const data JSON.parse(event.data); outputDiv.innerHTML data.word; // 逐字追加 if (data.is_end) { outputDiv.innerHTML \n---结束---\n; } }); // 监听自定义的 end 事件 eventSource.addEventListener(end, function(event) { outputDiv.innerHTML \n[系统] ${event.data}\n; eventSource.close(); // 收到结束事件后主动关闭连接 }); // 监听错误事件 eventSource.onerror function(error) { console.error(EventSource 错误:, error); outputDiv.innerHTML \n[错误] 连接异常或已关闭\n; if (eventSource) { eventSource.close(); } }; } function closeSSE() { if (eventSource) { eventSource.close(); document.getElementById(output).innerHTML \n[手动] 已停止接收事件\n; eventSource null; } } /script /body /html用浏览器打开这个 HTML 文件点击按钮你将看到来自 FastAPI 服务器的消息被逐字推送到页面上。4.4 处理客户端断开连接在长时间运行的流中客户端可能随时关闭页面或断开连接。如果服务器继续向已关闭的连接写入数据会导致资源浪费和错误。上面的示例代码中我们通过if await request.is_disconnected():来检查连接状态。这是一个关键的生产环境实践。对于更复杂的场景你可能需要维护一个连接池并在生成器中捕获asyncio.CancelledError来清理资源。5. 处理来自其他后端服务的请求如 Java Spring在实际微服务架构中你的 FastAPI 流式接口可能被其他后端服务调用例如一个 Java Spring Boot 应用。这时调用方需要能够处理流式响应。5.1 使用 Spring RestTemplate 请求流式接口的常见坑一个常见的错误是直接使用RestTemplate.getForObject()或postForObject()这些方法会等待整个响应体返回从而阻塞直到流结束失去了流式的意义。正确的方法是使用RestTemplate.execute()配合ResponseExtractor或者使用WebClient响应式编程。错误示例会导致阻塞或 422 错误:// 可能导致 422 Unprocessable Entity如果接口需要特定参数或格式 String result restTemplate.getForObject(http://fastapi-server:8000/sse/chat-stream?questionhello, String.class);5.2 使用 Spring WebClient 消费 SSE 流WebClient是 Spring 5 引入的响应式 HTTP 客户端非常适合处理流式响应。首先在pom.xml中添加依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-webflux/artifactId /dependency然后编写消费代码import org.springframework.http.MediaType; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Flux; public class FastApiSSEClient { public FluxString consumeChatStream(String question) { WebClient client WebClient.create(http://localhost:8000); return client.get() .uri(uriBuilder - uriBuilder .path(/sse/chat-stream) .queryParam(question, question) .build()) .accept(MediaType.TEXT_EVENT_STREAM) // 关键接受 SSE 媒体类型 .retrieve() .bodyToFlux(String.class) // 将响应体转换为 FluxString 流 .doOnNext(event - { // 处理每一个接收到的事件块 System.out.println(收到事件: event); // 这里可以解析 event 字符串提取 data, event 等字段 }) .doOnError(error - System.err.println(请求出错: error.getMessage())) .doOnComplete(() - System.out.println(SSE 流结束)); } }在 Controller 或 Service 中调用GetMapping(/call-fastapi-stream) public FluxString callFastApiStream() { FastApiSSEClient client new FastApiSSEClient(); return client.consumeChatStream(如何学习 FastAPI?); }这样Spring 应用就能以非阻塞的方式消费 FastAPI 的 SSE 流并可以将这个Flux再次流式地返回给自己的前端客户端形成链式流式响应。5.3 解决 422 Unprocessable Entity 错误如果 Java 客户端收到 422 错误通常意味着请求体或查询参数不符合 FastAPI 接口的预期。检查以下几点查询参数格式确保 URL 中的查询参数正确编码。使用UriComponentsBuilder来安全构建 URL。请求头确保设置了正确的Accept头如MediaType.TEXT_EVENT_STREAM。FastAPI 接口定义确认你的 FastAPI 路由正确地定义了参数。例如上面的chat_stream函数定义了question: str 你好它是一个查询参数。如果 Java 端以 JSON Body 的形式发送就会导致 422。正确构建请求的示例import org.springframework.web.util.UriComponentsBuilder; String url UriComponentsBuilder.fromHttpUrl(http://localhost:8000/sse/chat-stream) .queryParam(question, 你的问题) .toUriString(); // 然后使用这个 url 进行请求6. 生产环境部署与配置优化在开发环境使用uvicorn main:app --reload运行没问题但上生产环境需要考虑性能、稳定性和可维护性。6.1 使用 Uvicorn 与 Gunicorn 部署对于生产环境推荐使用Gunicorn作为进程管理器配合Uvicorn工作进程来处理 ASGI 应用。这能提供更好的并发处理和资源管理。安装 Gunicornpip install gunicorn使用 Gunicorn 启动在项目根目录gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000-w 4: 启动 4 个工作进程。通常建议设置为(2 * CPU核心数) 1。-k uvicorn.workers.UvicornWorker: 指定使用 Uvicorn 的 Worker 类。-b: 绑定地址和端口。6.2 调整 Uvicorn 配置以适应流式请求默认情况下Uvicorn 有一些超时设置可能会影响长连接。可以通过配置文件或命令行参数调整。创建一个uvicorn_config.py文件# uvicorn_config.py import os # 工作进程数通常由 Gunicorn 管理这里可以注释掉 # workers int(os.getenv(WEB_CONCURRENCY, 2)) # 每个工作进程的线程数 (对于异步框架通常为1) worker_threads 1 # 关键配置限制请求行和头部大小防止恶意请求 limit_concurrency None # 最大并发连接数生产环境建议设置 limit_max_requests 1000 # 工作进程处理这么多请求后重启防止内存泄漏 timeout_keep_alive 5 # 保持连接的超时时间秒对于 SSE 可以适当增加通过配置文件启动uvicorn main:app --config uvicorn_config.py对于 SSE 长连接你可能需要增加timeout_keep_alive并确保反向代理如 Nginx也有相应的长超时配置。6.3 使用 Nginx 作为反向代理在生产环境中通常使用 Nginx 作为反向代理处理 SSL、静态文件、负载均衡和缓冲控制。一个针对 FastAPI 流式输出特别是 SSE优化的 Nginx 配置片段如下server { listen 80; server_name your_domain.com; # 重定向到 HTTPS (可选) return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name your_domain.com; ssl_certificate /path/to/your/cert.pem; ssl_certificate_key /path/to/your/key.pem; location / { proxy_pass http://127.0.0.1:8000; # 指向 Gunicorn/Uvicorn proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 以下配置对 SSE 和流式响应至关重要 proxy_buffering off; # 禁用代理缓冲确保数据实时推送 proxy_cache off; # 禁用缓存 proxy_read_timeout 86400s; # 设置很长的读超时适用于长连接 # 对于 SSE还需要以下头部 proxy_set_header Connection ; proxy_http_version 1.1; chunked_transfer_encoding off; # 如果上游服务器正确发送了 Transfer-Encoding: chunked这个可以关掉 # 或者使用 # proxy_set_header Upgrade $http_upgrade; # proxy_set_header Connection upgrade; } }配置完成后重启 Nginxsudo nginx -t # 测试配置 sudo systemctl restart nginx6.4 处理静态文件与 Admin 界面如果你使用了像fastapi-admin这样的扩展并且发现菜单不显示通常是静态文件路径或前端路由配置问题。确保Nginx 正确配置了静态文件路径。FastAPI 应用正确挂载了静态文件目录。前端路由模式如 History 模式与后端配置匹配。在 FastAPI 中挂载静态文件目录from fastapi.staticfiles import StaticFiles app.mount(/static, StaticFiles(directorystatic), namestatic)在 Nginx 中可以优先让 Nginx 处理静态文件以减轻应用服务器负担location /static { alias /path/to/your/static/files; expires 30d; }7. 常见问题排查与性能优化7.1 流式输出不实时或延迟高现象数据在服务器端已经生成但客户端很久才收到或者一次性收到所有数据。可能原因与解决方案代理服务器缓冲这是最常见的原因。Nginx、Apache 或云负载均衡器默认会缓冲响应。检查查看 Nginx 配置中proxy_buffering是否设置为on。解决在 Nginx 的location块中设置proxy_buffering off;。同时在 FastAPI 的响应头中设置X-Accel-Buffering: no如前面示例所示。客户端缓冲某些 HTTP 客户端库或浏览器可能会缓冲数据。检查尝试使用curl -N测试如果curl是实时的而浏览器不是问题可能在前端。解决确保前端使用正确的 API如EventSource或fetch处理response.body流。生成器内部阻塞如果在生成器中使用同步的、阻塞的 I/O 操作如time.sleep()而不是asyncio.sleep()会阻塞整个事件循环。检查检查生成器函数中是否有同步睡眠、同步文件读写或同步网络请求。解决将所有 I/O 操作改为异步版本使用async/await。7.2 连接过早断开或超时现象流式连接在运行一段时间后自动断开前端收到错误或重连。可能原因与解决方案代理或服务器超时设置过短Nginx、负载均衡器或操作系统有默认的 keep-alive 或读写超时。检查Nginx 的proxy_read_timeout默认可能是 60s。解决对于长连接将其设置为一个很大的值如86400s一天。在 Uvicorn/Gunicorn 层面调整timeout_keep_alive。防火墙或中间件中断空闲连接某些网络设备会杀死长时间空闲的 TCP 连接。解决在 SSE 实现中定期发送注释行以:开头的行作为心跳包保持连接活跃。async def event_generator_with_heartbeat(): # ... 你的业务逻辑 ... # 每隔 15 秒发送一个心跳 last_heartbeat time.time() while True: await asyncio.sleep(1) if time.time() - last_heartbeat 15: yield : heartbeat\n\n # SSE 注释行客户端会忽略 last_heartbeat time.time() # ... yield 业务数据 ...7.3 内存泄漏与资源管理现象随着流式连接数增加服务器内存持续增长。可能原因与解决方案生成器未正确关闭如果客户端断开连接但服务器端的生成器还在运行并持有资源如数据库连接、文件句柄。解决务必在生成器内部检查await request.is_disconnected()并在断开时break循环。使用try...finally或异步上下文管理器确保资源释放。async def event_generator(): expensive_resource acquire_resource() try: while not await request.is_disconnected(): # ... 产生数据 ... yield data finally: release_resource(expensive_resource) # 确保资源被释放未限制并发连接数恶意攻击或设计缺陷可能导致海量长连接耗尽服务器资源。解决在应用层面或网关层面如 Nginx设置最大并发连接数限制。Uvicorn 可以通过--limit-concurrency参数设置。7.4 性能优化清单优化项操作预期效果使用异步生成器确保数据生成函数是async def并使用await进行 I/O。高并发下性能显著提升避免阻塞事件循环。禁用代理缓冲Nginx 设置proxy_buffering off;响应头加X-Accel-Buffering: no。实现真正的实时流式传输。设置合理超时Nginxproxy_read_timeout调大Uvicorntimeout_keep_alive调整。避免长连接被意外中断。添加心跳机制在 SSE 流中定期发送: heartbeat\n\n。保持连接活跃防止被中间设备断开。连接状态检查在生成器循环中定期检查request.is_disconnected()。及时释放已断开客户端的服务器资源。限制资源使用使用连接池管理数据库/外部服务连接避免每个请求创建新连接。防止资源耗尽提高整体稳定性。监控与日志记录流式连接的建立、断开和错误监控服务器内存和连接数。快速定位问题了解系统负载。8. 扩展方向与最佳实践掌握了基础流式和 SSE 后可以考虑以下方向深化应用。8.1 结合 WebSocket 实现全双工通信对于需要客户端和服务器频繁双向交互的场景如在线聊天室、实时协作可以将 SSE 升级为 WebSocket。FastAPI 对 WebSocket 有很好的支持from fastapi import FastAPI, WebSocket app.websocket(/ws) async def websocket_endpoint(websocket: WebSocket): await websocket.accept() try: while True: # 接收客户端消息 data await websocket.receive_text() # 处理并回复 await websocket.send_text(f你说了: {data}) except Exception as e: print(fWebSocket 错误: {e}) finally: await websocket.close()8.2 流式处理文件上传与下载StreamingResponse同样适用于大文件下载。对于文件上传可以使用UploadFile并流式读取其内容避免将整个文件加载到内存。流式下载大文件示例import aiofiles from fastapi.responses import StreamingResponse app.get(/download-large-file) async def download_large_file(): file_path path/to/very/large/file.zip async def file_sender(): async with aiofiles.open(file_path, rb) as f: chunk await f.read(65536) # 每次读取 64KB while chunk: yield chunk chunk await f.read(65536) return StreamingResponse( file_sender(), media_typeapplication/octet-stream, headers{Content-Disposition: fattachment; filenamelarge_file.zip} )8.3 集成到现有异步生态FastAPI 的流式输出可以轻松与异步数据库驱动如asyncpg、aiomysql、异步 Redis 客户端如aioredis、以及异步任务队列如Celerygevent或ARQ结合。例如你可以从异步数据库游标中流式读取查询结果并直接推送给客户端。8.4 安全与认证流式端点同样需要保护。你可以在流式路由上使用 FastAPI 的依赖注入系统进行认证和授权。from fastapi import Depends, HTTPException from fastapi.security import OAuth2PasswordBearer oauth2_scheme OAuth2PasswordBearer(tokenUrltoken) async def get_current_user(token: str Depends(oauth2_scheme)): # 验证 token返回用户信息 user authenticate_user(token) if not user: raise HTTPException(status_code401, detail无效凭证) return user app.get(/secure-stream) async def secure_stream(current_user: dict Depends(get_current_user)): async def generator(): yield fdata: 欢迎, {current_user[username]}\n\n # ... 其余流式逻辑 ... return StreamingResponse(generator(), media_typetext/event-stream)流式输出是构建现代、响应式 Web 应用的关键技术。从简单的文本流到复杂的实时事件系统FastAPI 凭借其异步特性和清晰的抽象让开发者能够以简洁的代码实现高性能的数据推送。关键在于理解不同流式协议分块传输、SSE、WebSocket的适用场景妥善处理连接生命周期和资源管理并在生产环境中配置好反向代理和超时参数。当你需要将生成式 AI 的回复逐字呈现或将服务器日志实时投射到运维面板时一个精心设计的 FastAPI 流式接口将是坚实可靠的基础。
返回列表