type
Post
status
Published
date
Dec 4, 2025
slug
summary
tags
category
icon
password
在 React Native (Expo/CLI) 中使用
@aws-sdk/client-s3 和 @aws-sdk/lib-storage 上传图片时,看似简单的逻辑却隐藏了多个环境兼容性深坑。本文记录了从报错到完美运行的全过程。🛠️ 技术栈
- Framework: React Native / Expo
- SDK: AWS SDK for JavaScript v3 (
@aws-sdk/client-s3,@aws-sdk/lib-storage)
- Key Feature: Multipart Upload (多部分上传)
🛑 遇到的主要报错 (The Pits)
1. 格式不支持 (Body Data Error)
报错信息:
[Error: Body Data is unsupported format, expected data to be one of: string | Uint8Array | Buffer | Readable | ReadableStream | Blob;.]
原因分析:
虽然 AWS SDK 文档说支持
Blob,但在 React Native 的 Hermes 引擎或特定环境下,直接将 fetch(uri).blob() 传给 SDK 经常失败。RN 的 Blob 实现与 Node.js 或标准 Web 环境存在差异。解决方案:
必须将 Blob 转换为
Uint8Array。这是 AWS SDK 在所有环境下兼容性最好的二进制格式。2. 环境缺失 (Prototype undefined)
报错信息:
[TypeError: Cannot read property 'prototype' of undefined] 或 Buffer is not defined
原因分析:
AWS SDK v3 深度依赖 Node.js 的核心模块(主要是
buffer 和 stream)。React Native 运行在 JSC/Hermes 环境中,默认没有这些全局变量。解决方案:
安装 polyfill 库并在入口处强制注入
global.Buffer。3. 方法缺失 (blob.arrayBuffer is undefined)
报错信息:
[TypeError: blob.arrayBuffer is not a function]
原因分析:
较新的 Web 标准中 Blob 有
.arrayBuffer() 方法,但 RN 的 Blob 实现(尤其是旧版本或某些 Expo 版本)尚未完全支持此方法。解决方案:
使用经典的
FileReader API 将 Blob 读取为 ArrayBuffer。4. 动态导入失败 (Unknown module)
报错信息:
[Error: Requiring unknown module "xxxx".]
原因分析:
为了节省性能尝试在函数内部使用
await import(...) 动态加载 SDK,但这会导致 Metro 打包器在解析依赖图时出错,或者缓存更新不及时。解决方案:
老老实实使用顶层 静态导入 (Static Import)。
✅ 最终解决方案
Step 1: 安装依赖
除了 AWS SDK,还需要安装必要的 Polyfill 库。
Step 2: 完整代码实现 (Hooks 封装)
💡 避坑总结 (Checklist)
- Polyfills 是必须的:不要抱侥幸心理,
buffer,url-polyfill,get-random-values这三剑客必须装。
- Uint8Array 是万金油:不要直接传
Blob给 SDK 的Body,React Native 处理不好。始终使用fetch -> blob -> FileReader -> ArrayBuffer -> Uint8Array的链路。
- 不要使用动态导入:RN Metro 对
await import()支持不稳定,使用顶层import并重启 Metro (npm start -- --reset-cache)。
- 全局 Buffer 注入:确保代码执行前
global.Buffer已经被赋值,通常放在入口文件或工具文件的最顶部。
提示:如果修改了 Polyfill 配置后仍然报错,记得清除 Metro 缓存重启! npx expo start -c 或 npm start -- --reset-cache