React Native上传音/图片到S3后文件损坏且类型为application/octet-stream
问题分析与解决方案
核心问题原因
你的代码存在两个关键问题,直接导致文件损坏和ContentType异常:
二进制数据处理错误
react-native-base64的decode方法返回的是字符串,而非AWS S3上传所需的二进制Buffer/Uint8Array。直接将该字符串作为Body上传会造成文件编码混乱,S3无法识别你设置的ContentType,最终 fallback 为application/octet-stream,同时文件内容损坏。多余的
createBucket调用createBucket是创建S3存储桶的接口,若你的桶已存在,这个调用完全多余,还可能干扰上传流程的异步逻辑,应直接移除。
修正方案
1. 正确处理二进制文件数据
无需将文件转base64再解码,推荐直接将base64内容转换为Uint8Array作为上传Body:
const base64_data = await RNFS.readFile(fPath, 'base64'); // 将base64转换为Uint8Array(符合S3上传要求的二进制格式) const uint8Array = Uint8Array.from(atob(base64_data), c => c.charCodeAt(0));
2. 移除多余的createBucket调用
直接调用s3bucket.upload即可,无需预先执行创建桶的操作。
修正后的完整代码
import RNFS from 'react-native-fs'; import AWS from 'aws-sdk'; uploadFileToS3 = async (file, fileInfo, details) => { const BUCKET_NAME = my_bucket; const REGION = my_region; const IAM_USER_KEY = my_key; const IAM_USER_SECRET = my_secret; const s3bucket = new AWS.S3({ accessKeyId: IAM_USER_KEY, secretAccessKey: IAM_USER_SECRET, region: REGION, signatureVersion: 'v4', }); const contentType = fileInfo.mimeType; const contentDeposition = `inline;filename="${fileInfo.name}"`; const fPath = file; // 读取base64并转换为符合要求的二进制格式 const base64_data = await RNFS.readFile(fPath, 'base64'); const uint8Array = Uint8Array.from(atob(base64_data), c => c.charCodeAt(0)); return new Promise((resolve, reject) => { const params = { Bucket: BUCKET_NAME, Key: `my_folder/${fileInfo.name}`, Body: uint8Array, ContentDisposition: contentDeposition, ContentType: contentType, }; s3bucket.upload(params, (error, data) => { if (error) { reject(error); } else { resolve(data); } }); }); };
额外检查项
- 上传完成后,登录AWS控制台查看S3对象的元数据,确认
Content-Type是否正确设置为你指定的值(如audio/wav、image/jpeg)。 - 若下载时仍出现ContentType异常,检查是否有S3桶的生命周期规则或CloudFront配置(如果使用CDN)覆盖了响应头。
内容的提问来源于stack exchange,提问作者user1099859
相关产品推荐
相关产品推荐

