如何使用axios发送携带图片的POST请求(React+Django场景)
文件上传400错误修复方案
错误原因
文件上传场景不能使用默认的application/json格式传参:
- 直接传递
File对象会被JSON序列化逻辑处理为无效值,后端无法解析到合法的文件内容 - 仅传递文件名字符串没有携带实际文件二进制数据,完全不符合Django
ImageField的字段校验规则
两种写法都会触发序列化器校验失败,返回400错误。文件上传必须使用multipart/form-data编码格式提交请求。
前端修改(React + Axios)
核心改动是用FormData对象组装所有请求参数,不要手动设置Content-Type请求头,让浏览器自动生成带正确boundary分隔符的请求头。
修改后的TestForm.jsx代码:
import React, {useState} from 'react'; import axios from "axios"; // CSRF全局配置只需要初始化一次,不需要放在组件内部 axios.defaults.xsrfCookieName = 'csrftoken' axios.defaults.xsrfHeaderName = "X-CSRFTOKEN" function TestForm() { // title_image初始值设为null更合理 const [testInputs, setTestInputs] = useState({title: '', title_image: null, test_type: ''}); const handleClick = async (e) => { e.preventDefault(); const formData = new FormData(); // 追加普通字段 formData.append('author', 1); formData.append('title', 'sad'); formData.append('test_type', 2); // 追加图片文件,直接传File对象,不要传.name属性 if (testInputs.title_image) { formData.append('title_image', testInputs.title_image); } // 多对多字段通过同key多次append的方式传值,DRF可自动解析为列表 [1, 3, 4].forEach(id => formData.append('question', id)); [1, 2].forEach(id => formData.append('result', id)); try { const res = await axios({ method: 'POST', url: 'http://127.0.0.1:8000/api/tests/', data: formData // 禁止手动设置Content-Type,否则会丢失boundary导致上传失败 }) console.log('提交成功', res.data) } catch (err) { // 打印后端返回的校验错误,快速定位问题 console.log('提交失败', err.response?.data) } } return ( <div> <form> <input onChange={(event) => { setTestInputs({...testInputs, title_image: event.target.files[0]}); }} type="file" accept="image/*" /> <button type="button" onClick={handleClick}>提交</button> </form> </div> ); } export default TestForm;
后端修改(Django DRF)
你当前的视图逻辑只做了校验,没有实际保存数据,需要补充save()调用,同时可以打印序列化器错误方便排查问题。
修改后的views.py代码:
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from .serializers import TestSerializers class TestList(APIView): def post(self, request, format=None): serializer = TestSerializers(data=request.data) if serializer.is_valid(): # 校验通过后调用save()才会写入数据库、保存上传的图片到指定目录 serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) # 开发阶段可打印错误信息快速定位问题字段 print(serializer.errors) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
后端配置检查项
- 确认
settings.py中已经配置MEDIA_ROOT(图片本地存储路径)和MEDIA_URL(图片访问路由前缀) - 确认
TestSerializers中title_image字段为ImageField类型,外键、多对多字段支持主键传值即可,不需要额外调整解析逻辑
内容的提问来源于stack exchange,提问作者Vahe Hakobjanyan
相关产品推荐
相关产品推荐

