如何在FastAPI中手动创建带content_type的UploadFile实例?
手动创建FastAPI UploadFile实例时设置content_type的解决方案
问题背景
我正在为FastAPI应用编写测试,其中ImageRecord类的upload_image方法(签名为async def upload_image(file: UploadFile, s3_client=None) -> 'ImageRecord')负责将图片上传至S3。需要通过moto模拟的S3存储桶直接调用该方法测试,无法通过HTTP请求调用API。
目前手动创建UploadFile的代码为:
contents = open("resc/valid_image.jpg", "rb").read() upload_file = UploadFile(filename="test_image.jpg", file=io.BytesIO(contents))
但该实例的content_type为None,导致上传时出现错误:
Invalid type for parameter ContentType, value: None, type: <class 'NoneType'>, valid types: <class 'str'>
FastAPI自动创建的UploadFile会从请求头获取content_type,但手动创建时无法通过构造参数设置,需要解决如何为测试创建带content_type的UploadFile实例,或是否需要重构代码从内容推断类型的问题。
解决方案
1. 直接赋值content_type属性
UploadFile是普通类实例,手动创建后可以直接给content_type属性赋值,无需通过构造参数:
import io from fastapi import UploadFile contents = open("resc/valid_image.jpg", "rb").read() upload_file = UploadFile(filename="test_image.jpg", file=io.BytesIO(contents)) # 直接设置对应图片类型的content_type upload_file.content_type = "image/jpeg"
2. 从文件内容自动推断MIME类型
如果不想硬编码类型,可以用python-magic库根据文件内容自动识别:
- 先安装依赖:
# Windows系统 pip install python-magic python-magic-bin # Linux/macOS系统 pip install python-magic
- 修改测试代码:
import magic import io from fastapi import UploadFile contents = open("resc/valid_image.jpg", "rb").read() upload_file = UploadFile(filename="test_image.jpg", file=io.BytesIO(contents)) # 从文件内容推断MIME类型 upload_file.content_type = magic.from_buffer(contents, mime=True)
3. 重构upload_image方法(可选)
如果希望业务代码能兼容content_type为空的场景,可以在方法内添加自动推断逻辑:
import magic from fastapi import UploadFile class ImageRecord: async def upload_image(self, file: UploadFile, s3_client=None) -> 'ImageRecord': # 若content_type为空,从文件内容推断 if not file.content_type: # 读取文件内容 file_content = await file.read() file.content_type = magic.from_buffer(file_content, mime=True) # 重置文件指针到开头,避免后续读取空内容 await file.seek(0) # 执行S3上传逻辑 # ... return self
内容的提问来源于stack exchange,提问作者MrDeveloper
相关产品推荐
相关产品推荐

