React Native调用Google Drive API上传文件遇格式错误求助
解决React Native向Google Drive API发送multipart/form-data的"Malformed multipart body"错误
常见问题原因及解决方案
1. Metadata字段的FormData构造方式错误
React Native的FormData.append方法对JSON类型字段的处理逻辑和浏览器/Postman存在差异,直接传递JSON字符串并指定type无法生成符合要求的multipart结构。正确做法是将JSON数据包装成Blob,并指定对应文件名(模拟Postman中上传JSON文件的行为):
const metadata = { name: fileName, mimeType: fileMimeType, description: fileDescription, parents: [GOOGLE_DRIVE_FOLDER_ID] }; // 将metadata转为Blob并指定文件名 formData.append("metadata", new Blob([JSON.stringify(metadata)], { type: 'application/json' }), 'metadata.json');
2. 文件URI格式兼容问题
React Native中iOS和Android的文件URI格式存在差异:
- iOS的URI通常以
file://开头,需要移除该前缀 - Android的URI可能是
content://格式,需确保权限正常或转换为标准文件路径
修改文件URI处理逻辑:
import { Platform } from 'react-native'; // 处理跨平台URI格式 const fileUri = Platform.OS === 'ios' ? file.assets[0].uri.replace('file://', '') : file.assets[0].uri; formData.append('file', { uri: fileUri, type: fileMimeType, name: fileName, });
3. 避免手动设置Content-Type头
React Native的fetch会自动为FormData类型请求生成包含正确boundary的Content-Type头,手动设置反而会导致boundary不匹配,引发格式错误。确保请求头中不要添加Content-Type: multipart/form-data。
修改后的完整代码
import { Platform } from 'react-native'; export const uploadToGoogleDrive = async (data) => { try { const accessToken = await signInWithGoogle(); const fileName = data.title; const fileDescription = data.description; const file = data.file; const fileMimeType = file.assets[0].mimeType; const formData = new FormData(); // 正确构造metadata部分 const metadata = { name: fileName, mimeType: fileMimeType, description: fileDescription, parents: [GOOGLE_DRIVE_FOLDER_ID] }; formData.append("metadata", new Blob([JSON.stringify(metadata)], { type: 'application/json' }), 'metadata.json'); // 处理跨平台文件URI const fileUri = Platform.OS === 'ios' ? file.assets[0].uri.replace('file://', '') : file.assets[0].uri; formData.append('file', { uri: fileUri, type: fileMimeType, name: fileName, }); const response = await fetch(`${GOOGLE_DRIVE_ENDPOINT}/files?uploadType=multipart`, { method: 'POST', headers: { 'Authorization': `Bearer ${accessToken}`, // 禁止手动设置Content-Type }, body: formData, }); if (!response.ok) { const errorText = await response.json(); console.log("Detailed Error:", errorText); throw new Error(`Error uploading file: ${response.statusText}, details: ${JSON.stringify(errorText)}`); } return await response.json(); } catch (error) { console.error("Upload error:", error); if (error.response) { console.error("Response data:", error.response.data); } else if (error.request) { console.error("Request details:", error.request); } else { console.error("Error:", error.message); } throw error; } };
替代方案
如果上述方法仍无法解决问题,可尝试以下方案:
- 使用
rn-fetch-blob库:该库对multipart请求的处理更接近原生,兼容性更好,适合复杂文件上传场景 - 切换为Google Drive API的
resumable上传类型:分块上传可规避multipart格式问题,同时支持大文件断点续传
内容的提问来源于stack exchange,提问作者Alexa
相关产品推荐
相关产品推荐

