FastAPI文件上传大小限制问题:如何提前校验文件大小?
FastAPI文件上传大小限制及大文件上传风险解析
一、不依赖Content-Length的实时大小校验方案
由于HTTP分块传输(Transfer-Encoding: chunked)无法提前获取文件总大小,只能通过边接收边校验的方式拦截超大文件。可以通过自定义FastAPI依赖项实现这一逻辑:
from fastapi import FastAPI, UploadFile, HTTPException, Depends import asyncio app = FastAPI() async def validate_file_size(file: UploadFile, max_size: int = 15 * 1024 * 1024): total_bytes = 0 chunk_size = 1024 * 1024 # 每次读取1MB块 while chunk := await file.read(chunk_size): total_bytes += len(chunk) if total_bytes > max_size: # 中断连接,停止接收后续数据 await file.close() raise HTTPException(status_code=413, detail=f"文件大小超过限制:最大{max_size//(1024*1024)}MB") # 重置文件指针,方便后续业务处理 await file.seek(0) return file @app.post("/upload") async def upload_file(file: UploadFile = Depends(validate_file_size)): # 处理合法文件逻辑 return {"filename": file.filename, "status": "success"}
这个方案的核心是逐块读取上传流,实时累加字节数,一旦超过限制就立即抛出异常并关闭文件连接,避免服务器继续接收超大文件数据。
二、未限制时超大文件上传的后果
如果服务器未做任何大小限制,用户上传100GB级别的大文件且磁盘空间不足时,会引发以下问题:
- 磁盘空间耗尽:服务器磁盘被占满后,所有需要写入磁盘的操作都会失败——包括应用日志记录、数据库写入、临时文件创建等,直接导致服务崩溃。
- 系统性能雪崩:大文件传输会持续占用磁盘IO、网络带宽和CPU资源,其他正常请求的响应速度会骤降,甚至出现超时、无响应的情况。
- 服务不可用:依赖磁盘的核心服务(如API、数据库)会因为无法写入数据而停止运行,需要手动清理磁盘空间才能恢复。
- 临时文件残留:FastAPI/Starlette会将上传文件先存储到临时目录(如
/tmp),如果上传中断,部分未清理的临时文件会继续占用磁盘空间。 - 带宽资源耗尽:大文件上传会占用大量网络带宽,导致其他用户的请求无法正常传输,引发网络拥堵。
三、额外防护建议
- 配合反向代理(如Nginx)设置
client_max_body_size,作为第一层拦截;同时可以配置请求超时时间,限制单请求的传输时长。 - 监控服务器磁盘使用率,设置告警阈值(如使用率达80%时触发告警),及时清理冗余数据。
- 定时清理临时目录:通过cron任务定期删除
/tmp目录下的过期临时文件,避免空间被无效占用。
内容的提问来源于stack exchange,提问作者Uğur Tümer
相关产品推荐
相关产品推荐

