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

React前端向Django上传图片失败,求Ajax上传解决方案

解决React上传图片到Django后端的问题

问题根源

你当前代码存在两个核心问题:

  1. React端存储的是浏览器伪造的文件路径(C:\\fakepath\\magnit.jpg),而非实际的文件对象,Django无法将字符串识别为文件。
  2. 上传文件必须使用FormData格式传输,普通JSON无法承载二进制文件数据,导致Django解析失败。

修复步骤

1. 修改React组件代码

更新文件选择逻辑和提交逻辑,改用FormData传输文件:

export function ProviderRegistration(){
    const[logoField, setLogoField] = useState(null) // 初始值设为null,用于存储文件对象
    const token = useSelector((state) => state.user.token)
    const [cookie, setCookie] = useCookies(['auth'])

    const confirm = () => {
        if (!logoField) return; // 未选中文件时不发起请求
        
        const formData = new FormData();
        formData.append('photo', logoField); // 将文件添加到FormData
        
        axios.post(`/providers/?username=${cookie.auth.login}`, 
            formData, 
            { headers: { "Authorization": `token ${token}` } }
        )
        .then(res => console.log(res))
        .catch(err => console.log(err))
    }

    return(
        <div className="registration-provider-container">
            <div className="registration-title">Provider registration</div>
            {/* onChange时获取文件对象,而非路径 */}
            <input 
                type="file" 
                className="registration-logo-add" 
                onChange={(e) => setLogoField(e.target.files[0])}
            />
            <button className="registration-confirm" onClick={confirm}>Confirm</button>
        </div>
    )
}

2. 确认Django Serializer配置

确保PutProviderSerializer中photo字段定义为FileField,以支持文件接收:

from rest_framework import serializers
from .models import Provider, User

class PutProviderSerializer(serializers.ModelSerializer):
    photo = serializers.FileField(required=True)
    user = serializers.PrimaryKeyRelatedField(queryset=User.objects.all())

    class Meta:
        model = Provider
        fields = ['user', 'photo'] # 根据你的模型实际字段调整

3. 优化Django视图的create方法

默认ModelViewSet的create方法已支持处理文件,但如果需要保留user字段自动填充逻辑,可调整为:

from rest_framework import status
from rest_framework.response import Response

class Providers(viewsets.ModelViewSet):
    filterset_class = ProvidersFilter
    queryset = Provider.objects.all()
    permission_classes = [IsAuthenticatedOrReadOnly, IsProviderPermission, IsOneToOneProviderPermission]
    
    def get_serializer_class(self):
        if self.action == 'list':
            return GetProviderSerializer
        else:
            return PutProviderSerializer

    def create(self, request):
        username = request.GET.get('username', '')
        user = User.objects.get(username=username).pk
        # 合并请求数据与文件信息
        data = request.data.copy()
        data.update({'user': user})
        # 传递数据和文件给序列化器
        serializer = self.get_serializer(data=data, files=request.FILES)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

关键注意事项

  • 不要手动设置Content-Type:axios会自动识别FormData并添加正确的multipart/form-data请求头(包含边界信息),手动设置会导致Django无法解析文件。
  • 文件对象获取:e.target.files[0]对应选中的第一个文件,如需支持多文件上传,可遍历e.target.files集合。
  • CSRF保护:若项目启用了CSRF保护,确保axios请求携带CSRF Token(使用django-cors-headers并正确配置可自动处理)。

内容的提问来源于stack exchange,提问作者Slllendy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 18:40:55