Django REST API文本文件上传测试报错求助
解决Django REST API文件上传的"提交数据不是文件"问题
嘿,我帮你排查下这个文件上传的问题!你遇到的错误提示说明请求格式不符合要求,Django REST Framework没法正确识别你传递的文件数据。下面分场景给你具体解决方案:
一、用requests库测试时的正确姿势
如果是用requests调用API,别直接传文件路径或裸临时文件对象,要严格按照multipart/form-data的格式构造请求:
import requests from tempfile import NamedTemporaryFile # 创建带正确扩展名的临时文件(服务器靠扩展名识别类型) with NamedTemporaryFile(suffix='.txt', delete=False) as temp_cover: temp_cover.write(b"这是测试求职信内容") cover_path = temp_cover.name # 构造files参数:每个字段是(文件名, 二进制文件对象, 内容类型)的元组 upload_url = "http://你的API地址/upload/" files = { 'cover_letter': ('my_cover.txt', open(cover_path, 'rb'), 'text/plain'), 'manuscript': ('my_paper.pdf', open('/本地路径/你的论文.pdf', 'rb'), 'application/pdf') } # 发送请求,requests会自动设置正确的Content-Type为multipart/form-data response = requests.post(upload_url, files=files) print(response.json())
关键注意点:
- 必须用
rb模式打开文件(二进制读),文本模式会破坏文件结构 - 文件名要带正确扩展名(比如
.txt、.pdf),不然服务器的类型验证会直接失败 - 无需手动设置请求头,requests会自动处理
multipart/form-data格式
二、Django测试用例里的正确写法
如果是在Django的TestCase中测试,要用SimpleUploadedFile包装文件数据,并且指定format='multipart':
from django.test import TestCase from django.core.files.uploadedfile import SimpleUploadedFile from rest_framework import status class FileUploadAPITest(TestCase): def test_valid_file_upload(self): # 创建模拟上传文件,带正确扩展名和内容类型 cover_file = SimpleUploadedFile( "cover_letter.txt", b"测试求职信内容", content_type="text/plain" ) manuscript_file = SimpleUploadedFile( "research_paper.pdf", b"%PDF-1.4\n%模拟PDF内容...", content_type="application/pdf" ) # 发送POST请求,必须指定format为multipart response = self.client.post( "/api/upload/", data={'cover_letter': cover_file, 'manuscript': manuscript_file}, format='multipart' ) # 验证请求成功 self.assertEqual(response.status_code, status.HTTP_201_CREATED)
三、服务器端的验证要配套
确保你的序列化器里的文件字段配置了正确的类型验证,比如用FileExtensionValidator:
from rest_framework import serializers from rest_framework.validators import FileExtensionValidator class UploadSerializer(serializers.Serializer): cover_letter = serializers.FileField( validators=[FileExtensionValidator(allowed_extensions=['txt', 'doc', 'pdf'])], max_size=1024*100 # 可选:限制文件大小为100KB ) manuscript = serializers.FileField( validators=[FileExtensionValidator(allowed_extensions=['pdf', 'doc', 'docx'])], max_size=1024*500 )
常见坑总结
- 不要用普通字典传文件数据,必须用
files参数(requests)或SimpleUploadedFile(测试用例)包装 - 文件名必须带正确扩展名,否则服务器无法识别文件类型
- 打开文件必须用二进制模式
rb,文本模式会导致文件数据损坏 - 测试用例里必须加
format='multipart',否则Django测试客户端会默认用application/json格式发送,导致文件无法被识别
内容的提问来源于stack exchange,提问作者Denis
相关产品推荐
相关产品推荐

