StreamingResponse可流式返回本地图片,避免FileResponse内存占用高问题;需用生成器分块yield二进制数据,设置正确media_type(如"image/jpeg"),路径须安全可靠。

用 StreamingResponse 返回本地图片流
FastAPI 本身不自动提供静态图片服务,如果只是想让前端通过 <img src="/path/to.jpg"> 直接加载一张已存的本地图片,最轻量的方式是用 StreamingResponse 流式读取文件并返回二进制内容。
关键点在于:不能用 FileResponse 简单返回(它适合小文件但会一次性加载进内存),而要用生成器配合 StreamingResponse 实现边读边发,尤其对大图更安全。
-
media_type必须设为正确的 MIME 类型,比如"image/jpeg"或"image/png",否则浏览器可能拒绝渲染 - 路径必须是服务端可读的绝对路径或相对于工作目录的可靠路径,别用用户传入的原始文件名拼接,防止路径遍历
- 生成器函数里要用
open(..., "rb"),且必须用yield from或分块yield,不能一次性read()后返回整个 bytes
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
app = FastAPI()
def stream_image():
with open("./static/photo.jpg", "rb") as f:
yield from f
@app.get("/photo")
def get_photo():
return StreamingResponse(stream_image(), media_type="image/jpeg")
上传后实时返回处理中的图片流(如缩略图生成)
如果你在接收上传的图片后,需要即时做裁剪、加水印、转格式等操作,并把结果“边生成边推”给前端(比如进度条 + 预览),就不能等全部处理完再返回——得用流式响应配合异步处理逻辑。
注意:这和“上传即存盘再返回 URL”的做法完全不同,适用于低延迟预览场景,但要求处理逻辑本身支持增量输出(例如 Pillow 的 save(..., progressive=True) 不行,得自己分块编码)。
前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。前端设计与 UI/UX 全方位优化专家。覆盖视觉层次、排版系统、色彩理论、响应式布局、交互体验、动画动效、无障碍访问、性能优化八大维度,帮助开发者将普通页面升级为高品质产品级界面。
立即学习“前端免费学习笔记(深入)”;
- 常见误区是试图在
StreamingResponse里调用同步图像库(如 PIL)的完整save(),结果还是阻塞+全量返回 - 真正流式生成图片需底层支持,比如用 OpenCV 写帧到内存 buffer,或用
io.BytesIO分段写入 JPEG SOF/SOS 数据(极少见,通常不值得) - 更实际的做法:用后台任务(
BackgroundTasks)保存处理结果,然后返回一个临时/preview?id=xxx路由,该路由再用StreamingResponse读取刚写好的临时文件
前端如何正确消费图片流?
浏览器原生不支持直接用 fetch 接收图片流并动态赋值给 <img> 的 src。你看到的“流式图片”基本都是假的——要么是 Base64 即时预览(没走服务器),要么是轮询一个不断更新的 URL,要么是用 <img> 指向一个固定路径,靠服务器缓存失效或 Nginx 的 proxy_cache_bypass 控制刷新。
- 若坚持用流,唯一可行路径是
fetch+response.body.getReader()+Uint8Array拼接,最后用URL.createObjectURL(new Blob([bytes], {type: "image/jpeg"}))赋给img.src;但这是全量接收后的“伪流”,无进度、无中断恢复 - 移动端 Safari 对
createObjectURL有内存限制,大图容易崩溃 - 真正需要流式体验的场景(如监控画面),应改用
video标签 + HLS 或 WebRTC,而不是硬套图片流
为什么不用 FileResponse?
FileResponse 看似更简单,但它内部会读取整个文件到内存再发出去,对 >10MB 的图片极易触发 OOM 或拖慢 uvicorn worker。而 StreamingResponse 只维持一个文件句柄和小缓冲区,内存占用恒定。
-
FileResponse适合已知小文件、且你信任文件路径安全的场景(比如/favicon.ico) -
StreamingResponse是唯一能控制读取节奏、支持超时中断、与BackgroundTasks配合做“上传-处理-流式返回”管道的方案 - 别忽略
headers={"Accept-Ranges": "bytes"}—— 加上它,前端视频控件或图片查看器才可能支持拖动进度条(对 MP4/WEBM 有效,对 JPG/PNG 无效)

















