You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 02:51:30