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

如何在Expo ReactNative中通过AXIOS POST将expo-picker-image图片保存至服务器?

解决Expo图片通过Axios上传至Django DRF无报错但未保存的问题

前端(Expo + Axios)排查与修正

1. 正确处理Expo ImagePicker返回的图片

Expo ImagePicker返回的uri是本地文件路径,必须转换成Blob才能被后端识别为文件,直接传入uri会导致上传失败。

示例代码:

import { ImagePicker } from 'expo-image-picker';
import axios from 'axios';

const pickAndUploadImage = async () => {
  const pickResult = await ImagePicker.launchImageLibraryAsync({
    mediaTypes: ImagePicker.MediaTypeOptions.Images,
    allowsEditing: true,
    quality: 1,
  });

  if (!pickResult.canceled) {
    // 将Expo本地uri转为Blob
    const blobResp = await fetch(pickResult.assets[0].uri);
    const imageBlob = await blobResp.blob();
    
    // 构造FormData
    const formData = new FormData();
    // 字段名`image`需和后端序列化器字段完全一致
    formData.append('image', imageBlob, `upload-${Date.now()}.jpg`);

    try {
      const uploadResp = await axios.post('http://你的DRF接口地址/upload/', formData, {
        headers: {
          // 禁止手动设置Content-Type!Axios会自动生成带boundary的请求头,手动设置会导致解析失败
        }
      });
      console.log('上传成功,图片地址:', uploadResp.data.image_url);
    } catch (err) {
      console.error('上传失败:', err.response?.data || err.message);
    }
  }
};

2. 前端关键注意点

  • 不要手动设置Content-Type: multipart/form-data,Axios会自动处理并添加必要的boundary标识。
  • FormData的append第三个参数是文件名,建议添加以帮助后端识别文件类型。

后端(Django DRF)配置与实现

1. 配置媒体文件存储路径

在项目settings.py中添加:

MEDIA_ROOT = BASE_DIR / 'media'
MEDIA_URL = '/media/'

开发环境下,在根urls.py中添加媒体文件访问路由:

from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    path('api/', include('你的APP.urls')),
    # 其他路由...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

2. 定义模型与序列化器

# models.py
from django.db import models

class UploadedImage(models.Model):
    # upload_to指定文件存储的子目录,会自动创建
    image = models.ImageField(upload_to='user_uploads/')
    uploaded_at = models.DateTimeField(auto_now_add=True)

# serializers.py
from rest_framework import serializers
from .models import UploadedImage

class UploadedImageSerializer(serializers.ModelSerializer):
    # 序列化时返回完整可访问的图片URL
    image_url = serializers.SerializerMethodField()

    class Meta:
        model = UploadedImage
        fields = ['id', 'image', 'image_url', 'uploaded_at']

    def get_image_url(self, obj):
        request = self.context.get('request')
        return request.build_absolute_uri(obj.image.url)

3. 编写上传视图

# views.py
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from .serializers import UploadedImageSerializer

class ImageUploadView(APIView):
    def post(self, request):
        # 传入request上下文用于生成完整URL
        serializer = UploadedImageSerializer(data=request.data, context={'request': request})
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

4. 配置APP路由

在APP的urls.py中:

from django.urls import path
from .views import ImageUploadView

urlpatterns = [
    path('upload/', ImageUploadView.as_view(), name='image-upload'),
]

快速排查清单

  1. 前端:打印formData.get('image')确认是否为Blob对象,而非字符串uri。
  2. 后端:
    • 检查MEDIA_ROOT目录是否有读写权限,确保Django进程能创建文件。
    • 在视图中打印request.FILES,确认是否接收到上传的文件。
    • 核对序列化器字段名与前端FormData的键是否完全一致。
  3. 跨域:若前后端域名不同,需配置Django跨域(可使用django-cors-headers库)。

内容的提问来源于stack exchange,提问作者Eder Juárez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 14:33:01