React Service Worker无法向Django服务器上传Blob文件求助
问题排查与解决方案
核心问题分析
你遇到的两个错误本质上是两个关联问题:手动设置Content-Type导致后端解析失败,以及Service Worker传递/后端接收Blob时的流程错误。
1. 解决Content-Type: multipart/form-data导致的400错误
当使用FormData作为fetch请求的body时,绝对不要手动设置Content-Type: multipart/form-data。浏览器会自动生成包含boundary分隔符的正确请求头(比如multipart/form-data; boundary=----WebKitFormBoundaryxxxx),手动设置会覆盖这个自动生成的头,导致后端无法正确解析多部分表单数据,直接返回400。
修改background-worker.js中的请求头部分:
const headers = new Headers({ 'Authorization': `Token ${authToken}`, // 移除手动设置的Content-Type });
2. 解决Blob字段为空的问题
去掉Content-Type后Blob仍为空,需要从前端传递、后端接收两个环节排查:
前端环节:确认Blob传递与FormData构建
- 在Service Worker的
message事件中,检查接收到的blob是否为有效对象:this.addEventListener('message', async (event) => { const data = event.data; if (data.blob) { console.log('Received Blob:', data.blob.size, data.blob.type); // 确认size>0、type正确 // ...后续逻辑 } }); - 确保
FormData.append('blob', file)中的file是有效File对象:const file = new File([blob], fileName, { type: blob.type }); console.log('Created File:', file.size); // 确认文件大小正常
后端环节:修复ViewSet与Serializer的错误
你的ExerciseRecordViewSet的perform_create方法存在逻辑错误,违背了ModelViewSet的工作流程,可能导致文件解析失败:
perform_create不需要手动创建Serializer并返回Response,父类已经处理了请求验证、序列化、响应的流程- 直接操作
request.data容易引发未验证的错误,应该使用serializer.validated_data
修改后的perform_create:
from django.utils import dateformat class ExerciseRecordViewSet(viewsets.ModelViewSet): queryset = ExerciseRecord.objects.all() serializer_class = ExerciseRecordSerializer # ...保留get_queryset方法... def perform_create(self, serializer): # 从已验证的序列化数据中获取值 patient = serializer.validated_data['patient'] date = serializer.validated_data['date'] # 查询患者的所有关联训练ID patient_exercises_ids = [ pe.exercise.id for pe in PatientExercise.objects.filter(patient=patient) ] # 查询今日已完成的训练ID today_completed_exercise_ids = [ er.exercise.id for er in ExerciseRecord.objects.filter(date=date, patient=patient) ] # 判断是否完成所有训练 if set(patient_exercises_ids) == set(today_completed_exercise_ids): patient.completed_exercise_date = date.today() patient.save() # 调用父类方法保存数据 serializer.save()
同时检查你的ExerciseRecordSerializer,确保blob字段正确配置为FileField:
from rest_framework import serializers from .models import ExerciseRecord class ExerciseRecordSerializer(serializers.ModelSerializer): class Meta: model = ExerciseRecord fields = ['id', 'patient', 'exercise', 'date', 'video', 'review', 'commment', 'blob'] # 外键字段默认会用PrimaryKeyRelatedField,无需额外配置
最终验证步骤
- 前端移除手动
Content-Type头后,重新发送请求 - 后端控制台查看
request.data,确认blob字段不再是None - 检查Django媒体目录(
exercise_records/)是否生成了上传的文件
内容的提问来源于stack exchange,提问作者Tejas Vaij
相关产品推荐
相关产品推荐

