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

使用AWS Amplify Storage类在Expo中上传图片至S3的问题

解决Expo + AWS Amplify上传图片到S3的问题

嘿,我完全懂你的困扰——Expo环境下没法用react-native-fetch-blob,RN又不支持Blob,官方示例都是文本文档,想传图片确实有点卡壳。不过你提到的两个方向都是可行的,我给你拆解下具体实现步骤:

方案一:直接上传Base64到S3(最简单直接)

这是我最推荐的方案,不需要额外搭建服务,利用Amplify Storage的能力就能搞定。核心思路是把图片转成Base64字符串,然后上传时指定正确的Content-Type,S3会自动把它解析成图片文件。

具体步骤+代码示例

  1. 先搞定权限(结合你给出的代码)
import { Permissions } from 'expo';
import * as ImagePicker from 'expo-image-picker';

// 请求相机相册权限
async function requestPermissions() {
  const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
  if (status !== 'granted') {
    alert('需要获取相册权限才能上传图片哦');
    return false;
  }
  return true;
}
  1. 选择图片并转为Base64
    用Expo的ImagePicker获取图片,同时直接拿到Base64格式的数据:
async function pickImage() {
  const hasPermission = await requestPermissions();
  if (!hasPermission) return;

  const result = await ImagePicker.launchImageLibraryAsync({
    mediaTypes: ImagePicker.MediaTypeOptions.Images,
    allowsEditing: true,
    quality: 0.8, // 控制图片质量,减少Base64体积
    base64: true, // 关键:开启Base64返回
  });

  if (!result.cancelled) {
    await uploadImageToS3(result.base64, result.type);
  }
}
  1. 用Amplify Storage上传Base64
    注意要去掉Base64字符串开头的data:image/jpeg;base64,前缀,然后指定正确的contentType:
import { Storage } from 'aws-amplify';

async function uploadImageToS3(base64Data, mimeType) {
  // 去掉Base64前缀
  const cleanBase64 = base64Data.replace(/^data:image\/\w+;base64,/, '');
  
  try {
    const key = `uploads/${Date.now()}-image.${mimeType.split('/')[1]}`; // 生成唯一文件名
    const result = await Storage.put(key, cleanBase64, {
      contentType: mimeType, // 重要:指定图片的MIME类型,比如image/jpeg
      level: 'public', // 根据你的需求选public/private
    });
    console.log('图片上传成功!地址:', result.key);
    return result.key;
  } catch (error) {
    console.error('上传失败:', error);
  }
}

方案二:用Lambda中转上传(适合大图片场景)

如果你的图片很大,Base64会让体积膨胀30%左右,这时候可以用Lambda做中转,Expo把图片的二进制数据(或者Base64)发给Lambda,由Lambda上传到S3。

具体步骤

  1. 创建Lambda函数(Node.js)
    Lambda需要有S3的上传权限,代码示例:
const AWS = require('aws-sdk');
const s3 = new AWS.S3();

exports.handler = async (event) => {
  try {
    const { base64Data, fileName, mimeType } = JSON.parse(event.body);
    const buffer = Buffer.from(base64Data, 'base64');
    
    const params = {
      Bucket: '你的S3桶名',
      Key: `uploads/${fileName}`,
      Body: buffer,
      ContentType: mimeType,
      ACL: 'public-read' // 根据需求设置权限
    };
    
    await s3.putObject(params).promise();
    return {
      statusCode: 200,
      body: JSON.stringify({ url: `https://${params.Bucket}.s3.amazonaws.com/${params.Key}` })
    };
  } catch (error) {
    return {
      statusCode: 500,
      body: JSON.stringify({ error: error.message })
    };
  }
};
  1. 在Expo中调用Lambda API
    把图片转成Base64后,通过API Gateway调用Lambda:
async function uploadViaLambda(base64Data, mimeType) {
  const fileName = `${Date.now()}-image.${mimeType.split('/')[1]}`;
  const cleanBase64 = base64Data.replace(/^data:image\/\w+;base64,/, '');
  
  try {
    const response = await fetch('你的Lambda API Gateway地址', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        base64Data: cleanBase64,
        fileName,
        mimeType
      })
    });
    const result = await response.json();
    console.log('通过Lambda上传成功,地址:', result.url);
  } catch (error) {
    console.error('Lambda上传失败:', error);
  }
}

小提示

  • 如果用Base64方案,建议压缩图片质量(比如quality设0.7-0.8),减少传输体积
  • 确保你的Amplify Storage配置正确,S3桶的CORS规则允许Expo应用访问
  • Lambda方案记得给Lambda配置S3的PutObject权限,避免权限错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:29:18