django - 通过 Angular(使用 FormData)将文件上传到 django-rest-framework
问题描述
我已经在网上翻遍了所有可能的 StackOverflow 问题和博客文章,但我仍然面临问题。
我正在尝试使用 Angular 12 将文件上传到django-rest-framework
端点。
这是前端代码:
uploadCameraImage(id: CameraInterface["id"], image: File): Observable<CameraInterface> {
const formData: FormData = new FormData();
formData.append("image", image);
const httpOptions = {
headers: new HttpHeaders({
"Content-Type": "multipart/form-data",
"Content-Disposition": `attachment; filename=${image.name}`
})
};
return this.http.put<CameraInterface>(`${this.configUrl}/camera/${id}/image/`, formData, httpOptions);
}
这些是相关django-rest-framework
部分:
# This is the main base serializer used for other operations
class EquipmentItemSerializer(serializers.Serializer):
class Meta:
fields = [
'created_by',
'created',
'updated',
'brand',
'name',
'image',
]
read_only_fields = ['image']
abstract = True
# This is the base serializer only used for the image upload
class EquipmentItemImageSerializer(serializers.Serializer):
class Meta:
fields = ['image']
abstract = True
# This is the main serializer used for all other operations (create/delete...)
class CameraSerializer(EquipmentItemSerializer, serializers.ModelSerializer):
class Meta:
model = Camera
fields = '__all__'
# This is the serializer used for the image upload in the @action below
class CameraImageSerializer(EquipmentItemImageSerializer, serializers.ModelSerializer):
class Meta:
model = Camera
fields = EquipmentItemImageSerializer.Meta.fields
# This is the base view set
class EquipmentItemViewSet(viewsets.ModelViewSet):
renderer_classes = [BrowsableAPIRenderer, CamelCaseJSONRenderer]
permission_classes = [IsEquipmentModeratorOrReadOnly]
http_method_names = ['get', 'post', 'head', 'put', 'patch']
def get_queryset(self):
q = self.request.GET.get('q')
manager = self.get_serializer().Meta.model.objects
return manager.all()
def image_upload(self, request, pk):
obj = self.get_object()
serializer = self.serializer_class(obj, data=request.data, partial=True)
# NOTE: I have to do this because FileUploadParser hardcodes 'file' while my model has 'image' :(
serializer.initial_data['image'] = serializer.initial_data['file']
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, HTTP_400_BAD_REQUEST)
class Meta:
abstract = True
# This the main view set
class CameraViewSet(EquipmentItemViewSet):
serializer_class = CameraSerializer
@action(
detail=True,
methods=['PUT'],
# NOTE THE DIFFERENT SERIALIZER FOR THE ACTION
serializer_class=CameraImageSerializer,
# I'VE TRIED ALL COMBINATIONS OF PARSERS INCLUIDING FormParser AND MultiPartParser
parser_classes=[FileUploadParser],
)
def image(self, request, pk):
return super(CameraViewSet, self).image_upload(request, pk)
使用此代码,生成的错误消息是我上传的文件不是有效图像。我深入调试了代码,它归结为用于打开图像Django
的ImageField
验证。PIL
我相信保存为 a 的文件Django
TemporaryFile
不仅仅是我发送的 PNG,而是我PUT
请求的整个正文。这是开头:
-----------------------------127295088417990690601368813565
Content-Disposition: form-data; name="image"; filename="9f1971c6-b8e6-4c5a-bd55-958b7fdd6ab1.png"
Content-Type: image/png
PNG
(binary data follows)
如果我添加FormParser
到我的解析器中image
@action
,我仍然会得到相同的行为。如果我还添加MultiPartParser
,我会得到一个空的request.data
and request.files
。
有人可以帮忙吗?
解决方案
推荐阅读
- c# - 在 .NET Core 2.2 中找不到 Microsoft.Extensions.EntityFrameworkCore 命名空间
- time-complexity - 这个程序的复杂性是什么。是 O(n) 吗?
- unity3d - DirectoryNotFoundException:找不到路径的一部分。(C# - 统一)
- python - 'from X import a' 有效,但 'import X; Xa'没有
- java - 采用 int 数组、int 索引和 int 值的方法
- node.js - 如何在 MongoDB 的聚合管道中获取当前时间戳?
- windows - 使用汇编语言打印字符串变量
- java - 由于 java.lang.VerifyError,打开 APK 失败
- python-3.x - 使用 pip3 安装 Jupyterlab 和使用 homebrew 安装 python3 后无法从终端启动 Jupyterlab
- php - 使用 PHP 生成链接以恢复订单