如何在Nuxt3中通过POST请求向Django DRF发送FormData?
问题:Nuxt3中转FormData请求到Django DRF时出现Unsupported Media Type错误
我尝试用Nuxt3作为中转服务器,将前端提交的包含文本数据和图片的FormData请求转发到Django DRF后端,提交表单时遇到Unsupported Media Type: /api/tasks/add/错误。直接用Postman请求后端接口可以正常工作,推测是Nuxt3未正确处理表单数据导致问题。
相关代码细节
前端页面组件代码(pages.vue)
const taskData = reactive({ title: '', city: '', description: '', category: route.params.cat_slug, subCat: '', image_1: [], image_2: [], image_3: [] }) const submitTaskForm = async () => { let formData = new FormData() formData.append('title', taskData.title) formData.append('city', taskData.city) formData.append('description', taskData.description) formData.append('category', taskData.category) formData.append('subCat', taskData.subCat) taskData.image_1.forEach((fileItem) => { formData.append('image_1', fileItem.file) }) taskData.image_2.forEach((fileItem) => { formData.append('image_2', fileItem.file) }) taskData.image_3.forEach((fileItem) => { formData.append('image_3', fileItem.file) }) const data = await useFetch('/api/tasks/add/', { method: 'POST', body: formData }) return data }
Nuxt服务器端API代码(/server/api/add.post.ts)
export default defineEventHandler(async (event) => { const body = await readBody(event) const access = getCookie(event, 'access') || null try { const data = await $fetch(process.env.API_BASE_URL + "/api/tasks/add/", { method: "POST", body: body, headers: { Authorization: "Bearer " + access, }, }) return data } catch (error) { console.log(error); return error } })
Django DRF视图代码
class TasksCreate(APIView): permission_classes = (permissions.IsAuthenticated,) serializer_class = TasksSerializer parser_classes = [MultiPartParser, FormParser] def post(self, request): data = self.request.data title = data['title'] city = data['city'] description = data['description'] category_slug = data['category'] subCat = data['subCat'] image_1 = request.FILES.get('image_1', "") image_2 = request.FILES.get('image_2', "") image_3 = request.FILES.get('image_3', "") try: if not Subcategories.objects.filter(slug=subCat, category__slug=category_slug).exists(): return Response( {'error': 'The subcategory does not correspond to the category.', }, status=status.HTTP_400_BAD_REQUEST ) task = Task.objects.create( title=title, city=city, description=description, slug='%s-%s' % (slugify(title), randint(1000, 10000)), category=get_object_or_404(Category, slug=category_slug), sub_category = get_object_or_404(Subcategories, slug=subCat), created_by=request.user, image_1=image_1, image_2=image_2, image_3=image_3, ) task.save() return Response( {'task': 'Task created successfully', }, status=status.HTTP_201_CREATED ) except Exception as e: print(e) return Response( {'error': 'Something went wrong when creating the task'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR )
解决方案
问题核心是Nuxt服务器端用readBody读取请求体时,会将multipart/form-data格式的数据解析为普通JSON对象,丢失了文件的二进制信息和正确的请求头结构,导致Django无法识别媒体类型。需要修改服务器端代码,正确处理multipart表单数据:
修改后的Nuxt服务器端API代码
export default defineEventHandler(async (event) => { // 读取原始multipart表单数据 const formDataItems = await readMultipartFormData(event); const access = getCookie(event, 'access') || null; // 重新构建FormData用于转发到Django const forwardFormData = new FormData(); formDataItems?.forEach(item => { if (item.filename) { // 处理文件字段:将二进制数据转为Blob并添加到FormData forwardFormData.append(item.name, new Blob([item.data], { type: item.type }), item.filename); } else { // 处理普通文本字段:将Buffer转为字符串 forwardFormData.append(item.name, item.data.toString()); } }); try { const data = await $fetch(process.env.API_BASE_URL + "/api/tasks/add/", { method: "POST", body: forwardFormData, headers: { Authorization: "Bearer " + access, // 不要手动设置Content-Type,$fetch会自动生成带boundary的正确头 }, }); return data; } catch (error) { console.error(error); return error; } });
关键说明
- 使用
readMultipartFormData替代readBody:该方法会保留原始multipart数据的结构,包括文件的二进制内容、文件名和MIME类型。 - 重新构建FormData:将读取到的multipart项重新组装成标准的FormData对象,确保转发时数据格式正确。
- 不要手动设置
Content-Type:手动设置会丢失自动生成的boundary参数,后端无法正确解析multipart数据,$fetch会自动处理FormData的请求头。
内容的提问来源于stack exchange,提问作者Minseven
相关产品推荐
相关产品推荐

