Python使用FastAPI实现文件上传接口的最佳方案

Written by

in

文章目录
  • 在现代 Web 应用中,文件上传几乎是所有系统的标配功能:无论是头像上传、文档提交,还是批量导入数据。 本文将详细介绍如何使用 FastAPI 快速、高效地实现文件上传接口,并给出进阶场景(如多文件上传、限制文件大小、异步保存文件等)的最佳实践。
  • FastAPI 内置了强大的文件上传支持,基于 starlette 的 UploadFile 对象实现。 它的底层使用 Python 的异步文件处理机制,性能优于传统的同步文件读取。 在 FastAPI 中,文件上传参数可以通过以下两种类型声明: File(…):用于声明表单中的文件字段。 UploadFile:封装上传文件对象,包含 filename、content_type、file 等属性。
  • 先看一个最简单的例子:上传一个文件并保存到服务器。 from fastapi import FastAPI, File, UploadFile import shutil import os app = FastAPI() UPLOAD_DIR = “uploads” os.makedirs(UPLOAD_DIR, exist_ok=True) @app.post(“/upload/”) async def upload_file(file: UploadFile = File(…)): file_path = os.path.join(UPLOAD_DIR, file.filename) # 保存文件 with open(file_path, “wb”) as buffer: shutil.copyfileobj(file.file, buffer) return {“filename”: file.filename, “content_type”: file.content_type}
  • FastAPI 支持一次性上传多个文件,只需将类型改为 List[UploadFile]: from typing import List from fastapi import UploadFile, File @app.post(“/upload/multiple/”) async def upload_multiple(files: List[UploadFile] = File(…)): saved_files = [] for file in files: file_path = os.path.join(UPLOAD_DIR, file.filename) with open(file_path, “wb”) as buffer: shutil.copyfileobj(file.file, buffer) saved_files.append(file.filename) return {“uploaded_files”: saved_files} 上传多个文件: curl -F “files=@a.png” -F “files=@b.jpg” http://127.0.0.1:8000/upload/multiple/
  • 上面的写入方式是同步的。如果文件较大,可能阻塞事件循环。 可以使用异步文件写入方式提升性能(推荐在高并发或大文件场景): import aiofiles @app.post(“/upload/async/”) async def upload_file_async(file: UploadFile = File(…)): file_path = os.path.join(UPLOAD_DIR, file.filename) async with aiofiles.open(file_path, ‘wb’) as out_file: while content := await file.read(1024): await out_file.write(content) await file.close() return {“filename”: file.filename} 提示:aiofiles 是一个异步文件操作库,可与 FastAPI 无缝协作。 安装依赖: pip install aiofiles
  • 在实际业务中,文件上传通常伴随表单数据(如用户ID、描述等)。 FastAPI 支持文件与表单字段混合处理: from fastapi import Form @app.post(“/upload/with_form/”) async def upload_with_form( user_id: int = Form(…), description: str = Form(“”), file: UploadFile = File(…) ): file_path = os.path.join(UPLOAD_DIR, file.filename) with open(file_path, “wb”) as buffer: shutil.copyfileobj(file.file, buffer) return {“user_id”: user_id, “description”: description, “filename”: file.filename}
  • 场景 推荐方案 上传头像、小文件 使用 UploadFile + 异步保存 批量导入Excel、CSV 使用 aiofiles 逐行读取,解析后入库 上传到云存储(如OSS、S3) 直接使用 boto3 或 oss2 SDK,将文件流转存至云端 接口网关安全限制 使用 Nginx / Traefik 限制文件大小和MIME类型 文件命名冲突 使用 UUID 或时间戳重命名文件
  • FastAPI 让文件上传的实现变得异常简单且高效。 通过本文的实践,你已经学会了: ✅ 基本文件上传与保存 ✅ 多文件与异步写入 ✅ 文件类型与大小校验 ✅ 表单与文件混合上传 ✅ 性能与安全最佳实践 接下来,你可以尝试: 实现一个图片上传 + 自动压缩接口 结合 JWT 用户认证,构建安全的文件上传系统 将文件元数据存储在数据库中,实现可追踪的文件管理系统
  • 目录
    • 引言
    • 一、FastAPI 文件上传的核心机制
    • 二、单文件上传示例
      • 说明:
    • 三、多文件上传
      • 四、异步写入与性能优化
        • 五、限制上传文件大小与类型
          • 限制大小(Nginx / Uvicorn 层)
          • 校验文件类型
        • 六、结合 Pydantic 校验表单 + 文件混合上传
          • 七、实际应用场景建议
            • 八、总结
              • 建议

            在现代 Web 应用中,文件上传几乎是所有系统的标配功能:无论是头像上传、文档提交,还是批量导入数据。 本文将详细介绍如何使用 FastAPI 快速、高效地实现文件上传接口,并给出进阶场景(如多文件上传、限制文件大小、异步保存文件等)的最佳实践。

            FastAPI 内置了强大的文件上传支持,基于 starletteUploadFile 对象实现。 它的底层使用 Python 的异步文件处理机制,性能优于传统的同步文件读取。

            在 FastAPI 中,文件上传参数可以通过以下两种类型声明:

            • File(...):用于声明表单中的文件字段。
            • UploadFile:封装上传文件对象,包含 filenamecontent_typefile 等属性。

            先看一个最简单的例子:上传一个文件并保存到服务器。

            from fastapi import FastAPI, File, UploadFile
            import shutil
            import os
            
            app = FastAPI()
            
            UPLOAD_DIR = "uploads"
            os.makedirs(UPLOAD_DIR, exist_ok=True)
            
            @app.post("/upload/")
            async def upload_file(file: UploadFile = File(...)):
                file_path = os.path.join(UPLOAD_DIR, file.filename)
                
                # 保存文件
                with open(file_path, "wb") as buffer:
                    shutil.copyfileobj(file.file, buffer)
                
                return {"filename": file.filename, "content_type": file.content_type}
            

            • UploadFile 是一个异步文件对象(底层为 SpooledTemporaryFile)。
            • file.file 是标准的类文件对象,可直接读写。
            • shutil.copyfileobj() 用于高效复制二进制数据流。

            访问接口:

            curl -F "file=@example.png" http://127.0.0.1:8000/upload/
            

            返回:

            {
              "filename": "example.png",
              "content_type": "image/png"
            }
            

            FastAPI 支持一次性上传多个文件,只需将类型改为 List[UploadFile]

            from typing import List
            from fastapi import UploadFile, File
            
            @app.post("/upload/multiple/")
            async def upload_multiple(files: List[UploadFile] = File(...)):
                saved_files = []
                for file in files:
                    file_path = os.path.join(UPLOAD_DIR, file.filename)
                    with open(file_path, "wb") as buffer:
                        shutil.copyfileobj(file.file, buffer)
                    saved_files.append(file.filename)
                return {"uploaded_files": saved_files}
            

            上传多个文件:

            curl -F "files=@a.png" -F "files=@b.jpg" http://127.0.0.1:8000/upload/multiple/
            

            上面的写入方式是同步的。如果文件较大,可能阻塞事件循环。 可以使用异步文件写入方式提升性能(推荐在高并发或大文件场景):

            import aiofiles
            
            @app.post("/upload/async/")
            async def upload_file_async(file: UploadFile = File(...)):
                file_path = os.path.join(UPLOAD_DIR, file.filename)
                async with aiofiles.open(file_path, 'wb') as out_file:
                    while content := await file.read(1024):
                        await out_file.write(content)
                await file.close()
                return {"filename": file.filename}
            

            提示:aiofiles 是一个异步文件操作库,可与 FastAPI 无缝协作。

            安装依赖:

            pip install aiofiles
            

            FastAPI 本身不限制文件大小。建议在 网关层(如 Nginx)限制上传大小:

            client_max_body_size 10M;
            

            你可以在接口中检查文件类型:

            ALLOWED_TYPES = ["image/png", "image/jpeg"]
            
            @app.post("/upload/image/")
            async def upload_image(file: UploadFile = File(...)):
                if file.content_type not in ALLOWED_TYPES:
                    return {"error": "Unsupported file type"}
                # 继续保存逻辑...
                return {"filename": file.filename}
            

            在实际业务中,文件上传通常伴随表单数据(如用户ID、描述等)。 FastAPI 支持文件与表单字段混合处理:

            from fastapi import Form
            
            @app.post("/upload/with_form/")
            async def upload_with_form(
                user_id: int = Form(...),
                description: str = Form(""),
                file: UploadFile = File(...)
            ):
                file_path = os.path.join(UPLOAD_DIR, file.filename)
                with open(file_path, "wb") as buffer:
                    shutil.copyfileobj(file.file, buffer)
                return {"user_id": user_id, "description": description, "filename": file.filename}
            

            场景 推荐方案
            上传头像、小文件 使用 UploadFile + 异步保存
            批量导入Excel、CSV 使用 aiofiles 逐行读取,解析后入库
            上传到云存储(如OSS、S3) 直接使用 boto3oss2 SDK,将文件流转存至云端
            接口网关安全限制 使用 Nginx / Traefik 限制文件大小和MIME类型
            文件命名冲突 使用 UUID 或时间戳重命名文件

            FastAPI 让文件上传的实现变得异常简单且高效。 通过本文的实践,你已经学会了:

            • ✅ 基本文件上传与保存
            • ✅ 多文件与异步写入
            • ✅ 文件类型与大小校验
            • ✅ 表单与文件混合上传
            • ✅ 性能与安全最佳实践

            接下来,你可以尝试:

            • 实现一个图片上传 + 自动压缩接口
            • 结合 JWT 用户认证,构建安全的文件上传系统
            • 将文件元数据存储在数据库中,实现可追踪的文件管理系统

            在实际项目中,推荐将文件上传逻辑封装为独立的服务模块(如 services/file_service.py), 结合日志(如 loguru)和异常处理中间件,让系统更加可维护与可追踪。

            以上就是Python使用FastAPI实现文件上传接口的最佳方案的详细内容,更多关于Python FastAPI文件上传接口的资料请关注风君子博客其它相关文章!

            您可能感兴趣的文章:

            • Python使用FastAPI实现大文件分片上传与断点续传功能
            • Python如何使用FastAPI玩转文件上传功能
            • Python利用fastapi实现上传文件

            站内搜索