Node.js fs写入文件仅保存图片链接未存储实际图片如何解决
问题根因
你的代码存在两个核心问题:
- 写入文件的入参是接口返回的
largeImageURL字段值,也就是图片的URL字符串本身,并没有发起请求拉取这个URL对应的实际图片二进制内容,所以文件里存的自然是URL文本。 - 即便直接请求图片地址,axios默认的响应类型是
json/text,会把二进制内容当文本解析,最终写入的文件也会损坏无法打开。
修改方案
需要调整三个核心逻辑:
- 拿到接口返回的图片URL后,额外发起一次针对该URL的请求,拉取真实图片内容
- 请求图片时给axios添加配置
responseType: 'arraybuffer',指定返回二进制格式数据 - 补全所有错误分支的异常抛出逻辑,避免Promise悬垂无法触发catch
修正后的可运行代码如下:
const fs = require('fs'); const axios = require('axios'); return new Promise((resolve, reject) => { // 本地文件已存在时直接读取返回 if (fs.existsSync(`./${imageDescription}`)) { fs.readFile(`./${imageDescription}`, (readErr, fileData) => { if (readErr) return reject(readErr); resolve(fileData); }); return; } // 第一步:请求接口获取图片真实地址 axios.get(imageUrl) .then(listRes => { const realImageUrl = listRes.data.hits[0].largeImageURL; // 第二步:请求真实图片地址,指定响应为二进制格式 return axios.get(realImageUrl, { responseType: 'arraybuffer' }); }) .then(imageRes => { // 第三步:将二进制图片内容写入本地文件 fs.writeFile(`./${imageDescription}`, imageRes.data, writeErr => { if (writeErr) return reject(writeErr); resolve(imageRes.data); }); }) .catch(err => reject(err)); });
如果需要处理大体积图片,推荐改用流模式写入,内存占用更低:
// 大图片流模式写入示例 axios.get(realImageUrl, { responseType: 'stream' }) .then(imageRes => { const writeStream = fs.createWriteStream(`./${imageDescription}`); imageRes.data.pipe(writeStream); writeStream.on('finish', () => { resolve(fs.readFileSync(`./${imageDescription}`)); }); writeStream.on('error', reject); }) .catch(err => reject(err));
内容的提问来源于stack exchange,提问作者Xavi Font
相关产品推荐
相关产品推荐

