Node.js中如何从Gunzip响应创建并保存有效文件?
解决Node.js node-fetch Gunzip响应保存图片无效的问题
问题分析
你遇到的问题是node-fetch返回的resp.body为Gunzip压缩流,但代码未正确处理解压流程,且缺少关键的错误监听与流事件处理,导致写入的文件不完整或损坏。
解决方案
方案1:让node-fetch自动处理gzip解压
请求时配置compress: true,node-fetch会自动识别响应的Content-Encoding并完成解压,此时resp.body就是可直接使用的图片数据流:
const fetch = require('node-fetch'); const fs = require('fs'); async function saveImage() { const resp = await fetch('你的图片请求URL', { compress: true // 开启自动解压 }); if (!resp.ok) throw new Error(`请求失败: ${resp.status}`); const dest = fs.createWriteStream('test.png'); resp.body.pipe(dest); dest.on('finish', () => { console.log('图片保存成功'); }); // 监听数据流错误,避免静默失败 resp.body.on('error', (err) => { console.error('数据流错误:', err); dest.destroy(err); }); dest.on('error', (err) => { console.error('文件写入错误:', err); }); } saveImage();
方案2:手动处理Gunzip流(适用于自定义解压逻辑场景)
若需手动处理压缩流,需确保监听所有可能的错误,并等待解压完成:
const fetch = require('node-fetch'); const fs = require('fs'); const zlib = require('zlib'); async function saveImage() { const resp = await fetch('你的图片请求URL'); if (!resp.ok) throw new Error(`请求失败: ${resp.status}`); // 判断响应是否为gzip压缩格式 const contentEncoding = resp.headers.get('content-encoding'); let stream = resp.body; if (contentEncoding === 'gzip') { stream = resp.body.pipe(zlib.createGunzip()); } const dest = fs.createWriteStream('test.png'); stream.pipe(dest); dest.on('finish', () => { console.log('图片保存成功'); }); // 监听解压流错误 stream.on('error', (err) => { console.error('解压错误:', err); dest.destroy(err); }); dest.on('error', (err) => { console.error('文件写入错误:', err); }); } saveImage();
关键注意点
- 错误监听:必须监听
Gunzip流与写入流的error事件,否则压缩或写入过程中的错误会静默失败,导致文件损坏。 - 事件选择:使用
finish事件而非end事件,finish会在所有数据写入磁盘后触发,确保文件完整。 - 响应校验:先通过
resp.ok确认请求成功(状态码200-299),避免处理错误响应的无效数据流。
内容的提问来源于stack exchange,提问作者poutyboi
相关产品推荐
相关产品推荐

