Expo React Native中Node.js接入Heroku react-simple-file-upload实现方法
Heroku环境下适配react-simple-file-upload的持久存储落地实现
前期方案选型
因为Heroku dyno自带的临时文件系统会在部署、扩容、休眠重启时清空所有本地写入文件,完全无法满足上传文件的持久留存需求,因此优先选型Heroku Elements市场内、提供S3兼容访问接口的托管对象存储附加组件。这类方案不需要改造原有“文件上传后将公开访问链接存入业务数据库”的业务逻辑,也能完美适配react-simple-file-upload的上传链路,无额外兼容成本。
第一步:挂载Heroku侧存储组件
- 在Heroku对应项目的附加组件面板,选择支持S3兼容接口的托管对象存储服务完成安装
- 安装完成后,系统会自动在项目的环境变量(Config Vars)中注入存储访问密钥、存储桶名称、服务端点、公开访问域名等配置项,所有密钥类配置直接从环境变量读取即可,禁止硬编码到业务代码中
第二步:改造Node.js后端的上传逻辑(替换原有multer本地存储)
原有基于multer的本地存储逻辑因为依托Heroku临时文件系统无法正常工作,需要将multer的存储引擎替换为对接S3兼容存储的实现,最小化对原有业务代码的改动:
- 安装依赖:执行
npm install multer-s3 aws-sdk完成对应存储引擎和SDK的安装 - 对比改造前后的multer配置:
原失效的本地存储配置(仅适合本地开发环境):
const multer = require('multer') // 原有逻辑:将文件写入本地uploads目录 const upload = multer({ storage: multer.diskStorage({ destination: './uploads', filename: (req, file, cb) => cb(null, `${Date.now()}-${file.originalname}`) }) })适配持久存储的配置:
const multer = require('multer') const S3 = require('aws-sdk/clients/s3') const multerS3 = require('multer-s3') // 从Heroku环境变量读取存储配置 const s3Client = new S3({ endpoint: process.env.STORAGE_SERVICE_ENDPOINT, accessKeyId: process.env.STORAGE_ACCESS_KEY, secretAccessKey: process.env.STORAGE_SECRET_KEY, s3ForcePathStyle: true }) // 改造后的存储逻辑:将文件直接写入托管存储桶 const upload = multer({ storage: multerS3({ s3: s3Client, bucket: process.env.STORAGE_BUCKET_NAME, acl: 'public-read', key: (req, file, cb) => cb(null, `app-uploads/${Date.now()}-${file.originalname}`) }) }) - 原有业务入库逻辑无需调整:multer-s3在文件上传完成后,会自动在接口返回值中生成文件的完整公开访问链接,直接按照原有逻辑将链接存入Heroku上的业务数据库即可。
第三步:对接Expo端react-simple-file-upload的直传逻辑
为了避免上传文件经过Node服务器中转消耗Heroku dyno的请求时长配额,可结合临时签名接口实现前端直传:
- 在Node后端新增临时签名生成接口:使用存储的访问密钥,为指定文件路径、指定权限生成有时效的临时上传签名,接口的用户校验逻辑和原有业务权限体系保持一致
- Expo端初始化react-simple-file-upload组件时,将上述签名接口的地址配置为组件的上传入口地址,组件会自动引导用户选择文件后,直传到托管存储桶
- 直传完成后,前端拿到存储返回的文件公开链接,直接调用原有业务的链接保存接口完成数据库写入即可
落地避坑提醒
- 绝对不要尝试在Heroku本地目录持久化上传文件:dyno的本地存储不具备跨实例、跨重启的持久能力,写入的文件会在任意实例变更时丢失
- 配置存储桶的跨域访问规则时,要将Expo开发调试的本地地址、生产发布的线上域名加入允许列表,避免前端直传时被跨域策略拦截
- 所有存储访问密钥、签名生成逻辑必须放在Node后端实现,禁止将密钥打包到前端Expo应用中,避免出现存储资源被盗用的风险
内容的提问来源于stack exchange,提问作者Fatma Mahmoud
相关产品推荐
相关产品推荐

