React Native 0.70本地JPG传OSS:fileData与formData的Content-Type确认
1. 你的代码中 fileData 的默认类型与对应 Content-Type
调用 ReactNativeBlobUtil.fs.readFile(filePath) 时,默认编码为 UTF-8,得到的 fileData 是 UTF-8 字符串。此时将其直接 append 到 FormData,该字段的 Content-Type 会被默认设置为 text/plain; charset=utf-8,完全不符合 JPG 图片的类型要求。
如果改用 readFile(filePath, 'base64') 读取为 Base64 字符串,默认情况下该字段的 Content-Type 仍为 text/plain,必须手动指定类型才能修正。
2. FormData 对应的请求 Content-Type
当你将 FormData 作为 fetch 请求体时,RN 的 fetch 会自动生成并设置请求的 Content-Type,格式为 multipart/form-data; boundary=xxxxxx(其中 boundary 是自动生成的分隔符)。如果你手动设置了 Content-Type(比如你尝试的 image/jpeg 或 application/octet-stream),会导致实际发送的请求头与签名校验时的 Content-Type 不匹配,直接触发校验失败。
3. OSS PUT 上传的正确姿势
OSS 的 PUT 接口通常要求直接将文件二进制内容作为请求体,而非用 FormData 封装(FormData 更多用于 POST 多字段提交场景),这也是你之前尝试多种 Content-Type 都失败的核心原因之一。
修正方案1:直接上传二进制数据
import ReactNativeBlobUtil from 'react-native-blob-util'; //v0.19.0 // 读取文件为 Blob 对象 const blob = await ReactNativeBlobUtil.fetch('GET', `file://${filePath}`).blob(); // 发起 PUT 请求 const response = await fetch(你的OSS上传URL, { method: 'PUT', headers: { 'Content-Type': 'image/jpeg', // 与图片类型匹配,签名时需一致 // 此处添加OSS签名所需的其他Header(如Authorization等) }, body: blob });
修正方案2:若必须使用 FormData
如果你的 OSS 接口要求用 FormData 提交,需确保正确设置字段的类型:
import ReactNativeBlobUtil from 'react-native-blob-util'; //v0.19.0 // 读取为 Base64 并转换为 Blob const base64Data = await ReactNativeBlobUtil.fs.readFile(filePath, 'base64'); const blob = ReactNativeBlobUtil.base64ToBlob(base64Data, 'image/jpeg'); const formData = new FormData(); // 手动指定文件名和类型 formData.append('file', blob, { filename: 'upload.jpg', type: 'image/jpeg' }); // 发起请求,不要手动设置 Content-Type const response = await fetch(你的OSS上传URL, { method: 'PUT', headers: { // 仅添加OSS签名所需Header,不要手动设置Content-Type }, body: formData });
关键注意点
- 签名校验失败的核心原因是设置的 Content-Type 与实际请求发送的不一致,务必确保签名时使用的 Content-Type 和请求头的完全匹配;
- PUT 上传优先选择直接传二进制,而非 FormData,更符合 OSS 接口的设计逻辑。
内容的提问来源于stack exchange,提问作者user938363

