Electron 11下node-fetch报错res.body.pipe is not a function问题求助
问题根因
- Electron v10+版本默认调整了渲染进程安全配置:
nodeIntegration默认设为false(禁用渲染进程Node.js集成),contextIsolation默认设为true(开启上下文隔离)。此时渲染进程内的fetch是浏览器原生的Fetch API,返回的res.body是WHATWG标准的ReadableStream,和Node.js的Stream不兼容,不存在pipe方法。 - 若升级Electron同时升级了
node-fetch到v3.x以上版本,该版本默认针对浏览器环境导出web fetch适配实现,同样返回web标准流,无pipe方法。 - electron-react-boilerplate的默认webpack配置会针对渲染进程优先打包依赖的浏览器端实现,会自动把
node-fetch指向适配浏览器的版本。
解决方案
方案1:调整配置保留渲染进程下载逻辑(安全性较低,仅建议无外部页面加载的内部应用使用)
- 修改主进程窗口创建的webPreferences配置:
const mainWindow = new BrowserWindow({ // 其余窗口配置不变 webPreferences: { nodeIntegration: true, contextIsolation: false, } })
- 修改渲染进程webpack配置(一般为项目内
webpack.renderer.config.js),强制指定node-fetch使用Node.js端实现:
module.exports = { // 其余配置不变 resolve: { alias: { 'node-fetch$': 'node-fetch/lib/index.js' } } }
方案2:迁移下载逻辑到主进程(官方推荐,安全性更高)
Electron主进程拥有完整的Node.js运行环境,不存在流兼容问题,通过IPC通信实现渲染进程触发下载:
- 主进程监听下载IPC事件,实现下载逻辑:
import { ipcMain } from 'electron'; import fetch from 'node-fetch'; import { createWriteStream } from 'fs'; import path from 'path'; ipcMain.handle('download-zip', async (_, downloadUrl, saveDir) => { const res = await fetch(downloadUrl); if (res.status !== 200) throw new Error('下载请求响应异常'); const savePath = path.join(saveDir, 'archive.zip'); const writeStream = createWriteStream(savePath); res.body.pipe(writeStream); return new Promise((resolve, reject) => { writeStream.on('finish', resolve); writeStream.on('error', reject); }); });
- 若开启了上下文隔离,在preload脚本中暴露IPC调用方法:
import { contextBridge, ipcRenderer } from 'electron'; contextBridge.exposeInMainWorld('electronAPI', { downloadZip: (url, saveDir) => ipcRenderer.invoke('download-zip', url, saveDir) });
- 调整渲染进程下载逻辑,通过IPC调用主进程能力:
const onDownload = async () => { const url = 'https://file-examples-com.github.io/uploads/2017/02/zip_10MB.zip'; const saveDir = './downloads'; try { await window.electronAPI.downloadZip(url, saveDir); console.log('end'); } catch (error) { console.log(error); } };
内容的提问来源于stack exchange,提问作者Valerxx22
相关产品推荐
相关产品推荐

