React前端向Django上传图片失败,求Ajax上传解决方案
解决React上传图片到Django后端的问题
问题根源
你当前代码存在两个核心问题:
- React端存储的是浏览器伪造的文件路径(
C:\\fakepath\\magnit.jpg),而非实际的文件对象,Django无法将字符串识别为文件。 - 上传文件必须使用
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
相关产品推荐
相关产品推荐

