如何解决Google Drive API+Axios+RNFS下载图片无法打开的问题?
问题描述
通过Google Drive API的files:get方法下载图片,并用RNFS保存到指定路径。Postman验证API响应正确,但保存后的.jpg文件无法打开。已尝试调整RNFS的encoding参数(base64/binary)和GET请求参数,均无效。
现有代码
Axios下载代码
downloadActivityCard: async function (id) { try { const params = { // fields: 'kind,driveId,mimeType,id,name,teamDriveId,thumbnailLink,webContentLink,modifiedTime', alt: 'media', responseType: 'arraybuffer', }; const dirPath = MAINDIRECTORY + '/FeaturedActivityCards/' + id; const filePath = `${dirPath}/cardImage.jpg`; let card = {}; //check if file exists if (await checkFileExists(filePath)) { throw new Error('This Activity Card is already downloaded'); } //set up the get URL, then call axios for response const downloadUrl = DRIVE_API_URLS.SEARCH_FILES + '/' + id + DRIVE_API_URLS.SEARCH_PARAMETERS; const response = await axios.get(downloadUrl, { params }).catch(error => { console.error('ERROR IN DOWNLOADING ACTIVITY CARD: ' + error); }); card = response.data; //make directory for the newly downloaded card, write the card into this path and return await makeDirectory(dirPath); await writeFile(true, filePath, card); return filePath; } catch (e) { console.log('ERROR IN DOWNLOADING ACTIVITY CARD: ' + e); } }
RNFS写入代码
export async function writeFile(isImage, filepath, content) { const options = { encoding: '', }; if (isImage) { options.encoding = 'base64'; } else { options.encoding = 'utf8'; } return RNFS.writeFile(filepath, content, options.encoding) .then(success => { console.log(`FILE WRITTEN!: ${filepath}`); }) .catch(err => { console.log(`RNFS writeFile: ${err.message}`); }); }
解决方案
问题核心是二进制数据处理不匹配:axios请求设置responseType: 'arraybuffer'后返回ArrayBuffer类型数据,但RNFS的writeFile在指定base64编码时,需要传入base64字符串而非原始二进制数据。以下两种修改方式任选其一即可:
方式一:将ArrayBuffer转为base64字符串后写入
修改Axios请求后的处理逻辑,把原始二进制数据转成base64格式:
// 替换原`card = response.data;`这一行 const buffer = Buffer.from(response.data); card = buffer.toString('base64');
RNFS的writeFile函数保持base64编码设置不变,即可正确写入图片。
方式二:直接写入二进制数据
RNFS支持直接写入二进制数据,无需转base64,修改以下两处:
- 调整Axios的
responseType为blob:
const params = { alt: 'media', responseType: 'blob', // 改为blob类型 };
- 更新RNFS的
writeFile函数,适配二进制数据写入:
export async function writeFile(isImage, filepath, content) { let encoding = 'utf8'; if (isImage) { encoding = 'binary'; // 图片使用binary编码 // 若响应是Blob类型,先转为Buffer if (content instanceof Blob) { const arrayBuffer = await content.arrayBuffer(); content = Buffer.from(arrayBuffer); } } return RNFS.writeFile(filepath, content, encoding) .then(success => { console.log(`FILE WRITTEN!: ${filepath}`); }) .catch(err => { console.log(`RNFS writeFile: ${err.message}`); }); }
额外优化:统一错误处理
移除Axios请求后的.catch链,利用外层try/catch统一捕获错误,避免response为undefined的情况:
// 修改原response获取代码 const response = await axios.get(downloadUrl, { params }); // 去掉后面的.catch(error => {...})
内容的提问来源于stack exchange,提问作者harmitg123
相关产品推荐
相关产品推荐

