React Native+Expo集成AWS S3上传报错:Cannot read property 'decode' of undefined
解决Expo React Native中AWS S3上传的URL构造错误
错误分析
你遇到的TypeError: Cannot read property 'decode' of undefined本质是React Native环境中缺失URL相关API的polyfill,或AWS SDK与RN的Blob/网络API兼容性问题——即使已导入react-native-url-polyfill/auto,也可能存在加载时机或其他依赖缺失的情况。
解决方案
1. 优先加载URL Polyfill
确保react-native-url-polyfill/auto是项目中第一个被导入的模块,在App.js最顶部添加:
import 'react-native-url-polyfill/auto'; // 之后再导入其他模块,比如React、AWS SDK等
避免在业务组件中局部导入,防止其他依赖先调用未被polyfill的API。
2. 替换Blob为ArrayBuffer/Base64
React Native的Blob实现与AWS SDK兼容性较差,改用ArrayBuffer处理文件内容,同时必须指定ContentType(否则S3会默认设为二进制类型,图片无法直接访问):
const handleUpload = async (pickerResult) => { try { const res = await fetch(pickerResult.uri); const arrayBuffer = await res.arrayBuffer(); const data = await client.send( new PutObjectCommand({ ACL: 'public-read', Bucket: S3_BUCKET, Key: `usergen-${Date.now().toString()}`, Body: arrayBuffer, ContentType: pickerResult.mimeType, // 关键:指定文件MIME类型 }) ); return data; } catch (err) { console.log(err); throw err; } };
3. 完善Metro配置
在metro.config.js中添加Node核心模块的polyfill,确保AWS SDK能正常解析依赖:
const { getDefaultConfig } = require('expo/metro-config'); const config = getDefaultConfig(__dirname); config.resolver.extraNodeModules = { ...config.resolver.extraNodeModules, url: require.resolve('react-native-url-polyfill'), buffer: require.resolve('buffer'), stream: require.resolve('stream-browserify'), }; module.exports = config;
同时安装所需依赖包:
npm install buffer stream-browserify
4. 优化S3Client初始化
将S3Client的初始化移到组件外部,避免每次组件渲染重复创建客户端:
// 组件外部初始化 import { S3Client } from '@aws-sdk/client-s3'; import { AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, S3_REGION } from '@env'; const client = new S3Client({ credentials: { accessKeyId: AWS_ACCESS_KEY_ID, secretAccessKey: AWS_SECRET_ACCESS_KEY, }, region: S3_REGION, }); const Memories = () => { // ... 组件逻辑 };
5. 验证AWS配置正确性
- 确认
S3_BUCKET为准确的桶名,无多余符号;S3_REGION与桶的实际区域完全一致 - 检查IAM用户权限:必须拥有
s3:PutObject权限,且桶的ACL或策略允许public-read访问
内容的提问来源于stack exchange,提问作者Jordy337
相关产品推荐
相关产品推荐

