FastAPI接口上传小文件时UploadFile内容为空问题
FastAPI生产环境下UploadFile读取小文件内容为空的问题解决
问题复现
生产环境中,使用FastAPI的UploadFile接收CSV文件时,小文件调用file.file.read()返回空内容,增加文件内容后可正常读取;但直接读取request.body()能获取完整内容。本地开发环境无此问题,生产启动命令为:
PYTHONPATH=/var/www/api/current /var/www/api/current/venv/bin/python /var/www/api/current/venv/bin/uvicorn main:app --reload --port=8004
可能原因
- 同步IO操作与异步上下文冲突:直接操作
file.file(底层是同步的SpooledTemporaryFile)在生产环境的异步事件循环中可能导致文件指针异常,小文件更容易触发此问题。 - 开发模式启动参数影响:生产环境使用
--reload(开发模式)启动Uvicorn,该模式下的文件处理逻辑与生产模式存在差异,可能导致请求体内容提前被消费。 - 代理/中间件的请求体缓存:若生产环境前端有Nginx等代理,可能存在请求体缓冲配置问题,导致小文件的请求体未完整传递给FastAPI。
解决方案
1. 使用UploadFile的异步读取方法
替换直接操作file.file的同步读取,改用UploadFile提供的异步read()方法,这是FastAPI推荐的方式,适配异步上下文:
from fastapi import UploadFile, FastAPI app = FastAPI() @app.post("/csv/file/preview") async def post_csv_file_preview(file: UploadFile): contents = await file.read() # 使用异步read方法 print(contents)
2. 重置文件指针位置
若必须操作底层文件对象,在读取前手动重置指针到文件开头,避免因指针位置异常导致读取为空:
@app.post("/csv/file/preview") async def post_csv_file_preview(file: UploadFile): file.file.seek(0) # 将文件指针重置到起始位置 contents = file.file.read() print(contents)
3. 改用生产模式启动Uvicorn
移除--reload参数,使用生产模式启动Uvicorn,避免开发模式的特殊逻辑影响:
PYTHONPATH=/var/www/api/current /var/www/api/current/venv/bin/python /var/www/api/current/venv/bin/uvicorn main:app --port=8004 --workers=4
(可根据服务器配置调整--workers数量)
4. 检查代理配置(如Nginx)
若使用Nginx作为反向代理,确保配置中允许完整传递请求体,例如添加或调整以下配置:
location / { proxy_pass http://localhost:8004; proxy_request_buffering off; # 关闭请求体缓冲,确保完整传递 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }
内容的提问来源于stack exchange,提问作者Bastien D
相关产品推荐
相关产品推荐

