提交的数据不是一个文件。请检查表单的编码类型
我当前正在用Postman测试一次上传多个文件(4张图片)。下面是在Postman中的配置方式。
关键字段是file_list,值是我上传到Postman的这4 张图片文件。我把Django REST Framework的视图配置成如下:
class PostImageValidate(APIView):
permission_classes = (IsAuthenticated, IsNotSuspended)
def put(self, request):
request_data = request.data.dict()
serializer = TempImageSerializer(data=request_data)
serializer.is_valid(raise_exception=True)
data = serializer.validated_data
file_list = data.get("file_list")
uploaded_files = data.pop(file_list)
results = []
for file in uploaded_files:
results.append({"filename": file.name, "size": file.size, "status": "Processed})
return Response({"message": "Images processed successfully", "results": results, "number of items": len(results)}, status=status.HTTP_201_CREATED)
class TempImageSerializer(serializers.Serializer):
file_list = serializers.ListField(child=serializers.FileField(max_length=150, allow_empty_file=False), allow_empty=False)
不过,在发出请求后,大约5 到6 秒,我得到了如下响应。
{
"file_list": {
"0": [
"The submitted data was not a file. Check the encoding type on the form."
],
"1": [
"The submitted data was not a file. Check the encoding type on the form."
],
}
}
# The key "0" ,"1" extends up to 460 with the same statement above.
以上问题我还没能解决。我的目标是确保它按预期返回Response。只有在确认这一点后,我才打算开始处理这些文件,相关的处理代码尚未插入。
解决方案
我写了一个最小可运行的测试代码来验证,问题似乎出现在 .dict() 上。
request_data = request.data.dict()
它会创建一个只包含单个文件的字典(即使有多个文件)- 如下所示
{'file_list': <InMemoryUploadedFile: lenna.png (image/png)>}
但代码需要的是一个列表(即使只有一个文件)- 如下所示
{'file_list': [<InMemoryUploadedFile: lenna.jpg (image/jpeg)>, <InMemoryUploadedFile: lenna.png (image/png)>]}
(因此后续它把这个单文件当作对象列表,从而在响应中产生了许多错误项)
如果跳过 .dict(),代码就能正确工作
request_data = request.data
# <QueryDict: {'file_list': [<InMemoryUploadedFile: lenna.jpg (image/jpeg)>, <InMemoryUploadedFile: lenna.png (image/png)>]}>
或者如果你确实需要标准的 dict,而不是 QueryDict,就使用标准的 dict(...)
request_data = dict(request.data)
# {'file_list': [<InMemoryUploadedFile: lenna.jpg (image/jpeg)>, <InMemoryUploadedFile: lenna.png (image/png)>]}>
也可以和 requests.FILES 一起工作
request_data = {"file_list": request.FILES.getlist("file_list")}
另一个问题出现在以下几行
file_list = data.get("file_list")
uploaded_files = data.pop(file_list)
它必须是字符串 "file_list",而不是变量 file_list
# no need to use `data.get()`
uploaded_files = data.pop("file_list")
用于测试的完整类
class PostImageValidate(APIView):
# permission_classes = (IsAuthenticated, IsNotSuspended)
def put(self, request):
print("\n=== put ===\n")
print("=== request.data ===")
print(request.data)
print("=== request.data.dict() ===")
print(request.data.dict())
print("=== request.data.lists() ===")
print(request.data.lists())
print(list(request.data.lists()))
print("=== dict(request.data) ===")
print(dict(request.data))
print('=== request.FILES.getlist("file_list") ===')
print(request.FILES.getlist("file_list"))
# request_data = request.data.dict() # WRONG
# request_data = dict(request.data)
request_data = request.data
# request_data = {"file_list": request.FILES.getlist("file_list")}
print("=== request_data ===")
print(request_data)
serializer = TempImageSerializer(data=request_data)
serializer.is_valid(raise_exception=True)
data = serializer.validated_data
# uploaded_files = data.pop("file_list")
uploaded_files = data.get("file_list")
print("=== uploaded_files ===")
print(uploaded_files)
results = []
for file in uploaded_files:
results.append(
{"filename": file.name, "size": file.size, "status": "Processed"}
)
output = {
"message": "Images processed successfully",
"results": results,
"number of items": len(results),
}
return Response(output, status=status.HTTP_201_CREATED)
我在控制台(Linux Mint)用 curl 进行了测试
curl -X PUT \
-F "[email protected]" \
-F "[email protected]" \
-F "other=Hello World!" \
http://127.0.0.1:8000/api/upload/
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。