Electron.js:如何为 window 创建单独的下载 webContents.session?
Electron.js: how to create a separate download webContents.session for a window?
我有一个 Electron file manager app,它为不同的目的创建了 2 windows:
quickView
用于预览本地文件的渲染器 window。它使用“will-download”侦听器通过阻止下载来检测不支持的文件。
main
主渲染器 window。它使用“will-download”侦听器来下载文件。
每个都有自己的 will-download
听众附加到他们的会话。但由于某种原因,quickView
监听器覆盖了 main
监听器。
Window 1
在下一行中,我正在为“主”进程创建一个 will-download
侦听器。此侦听器的目的是下载文件:
win.webContents.session.on('will-download', listener)
下一行中的windows.main
参数是上一行中的win
引用:
const resultInfo = await downloadManager.download(windows.main, {
Window 2
在下一行中,我正在为“quickView”window 创建一个 will-download
侦听器。此侦听器的目的是检测不支持的文件(在 Chromium 中触发下载事件)并阻止下载事件:
windows.quickViewWindow.webContents.session.once('will-download', _willDownloadHandler)
我还没有找到另一种方法来检测不受支持的文件,这就是我首先使用 will-download
事件的原因。
问题
出于某种原因,quickView
window 的 will-download
处理程序覆盖了 main
的处理程序:
当我在这里触发应用更新下载事件时(来自main
进程):
const resultInfo = await downloadManager.download(windows.main, {
它触发 quickView
渲染器的事件处理程序 window:
function _willDownloadHandler (event, item, webContents) {
...
windows.main.webContents.send('load:webview::failed', {path: fileURL})
部分修复
我通过为 quickView
window 的会话指定自定义分区名称,部分解决了 this commit 中的问题,因此它不使用默认会话,也不覆盖由 main
:
创建的 will-download
侦听器
主要流程:
windows.quickViewWindow = new electron.BrowserWindow({
...
webPreferences: {
partition: 'quickPreview',
...
windows.quickViewWindow.webContents.session.once(
'will-download',
(event, item, webContents) => {
event.preventDefault()
...
}
)
quickViewWindow.html:
ipcRenderer.on('load:webview', (event, data) => {
...
webviewNode.setAttribute('partition', 'quickPreview')
但是这个修复导致了另一个问题:
快速查看 window 在生产构建中停止工作(可能与协议不适用于非默认会话分区有关)
将自定义分区设置为 webview 会导致 Windows 协议 link 关联在创建包含此 webview 的 window 时在生产中弹出:
我认为这可能是由 electron-builder-plugin 创建的自定义 app://
协议引起的。弹出窗口似乎是由“应用程序”触发的 link.
或者可能是因为我在这条线附近的某处创建 window 时错误地设置了协议:
重现:
- 下载项目
git clone https://github.com/aleksey-hoffman/sigma-file-manager.git
cd sigma-file-manager
npm install
git checkout 47ce65b
npm run electron:build
- 安装来自
./dist_electron
的内置应用
- 在应用程序启动期间,您可以看到弹出窗口
备注:
我刚刚回滚了 47ce65b 提交并添加了一些测试值
所以更容易调试
要切换到最新提交并创建生产版本:
git checkout 5246252
npm run electron:build
electronMain.js
里面的所有console.log()
都显示在终端(命令行)window(不是开发者工具控制台)
要触发快速查看功能:
- Select 导航器页面上任何支持的文件(图像/文本/等)
- 按 Space(应该会打开快速视图 window)
要触发下载事件,您只需打开“导航器”页面并从互联网上拖放任何文件(或网站 URL)即可。它会触发错误的 will-download 事件处理程序(quickView window 的处理程序),您应该会看到控制台消息。
包含此 Web 视图的快速视图 window 是在 app.ready
事件上创建的。指定分区时,将在创建 quickView window 后立即弹出:
更新:
较小的复制示例:
我能够用这段代码重现它:
let window1 = null
let window2 = null
electron.app.on('ready', async () => {
createWindow1()
createWindow2()
setTimeout(() => {
console.log('trigger window 1 download')
window1.webContents.downloadURL('https://whosebug.com')
}, 1000)
})
function createWindow2 () {
window1.webContents.session.once('will-download', downloadHandler1)
window2.webContents.session.once('will-download', downloadHandler2)
}
function createWindow1 () {
window1 = new electron.BrowserWindow()
window1.loadURL('app://./quickViewWindow.html')
window1.webContents.session.once('will-download', downloadHandler1)
}
function createWindow2 () {
window2 = new electron.BrowserWindow()
window2.loadURL('app://./quickViewWindow.html')
window2.webContents.session.once('will-download', downloadHandler2)
}
function downloadHandler1 (event, item, webContents) {
console.log('window will-download handler 1')
}
function downloadHandler2 (event, item, webContents) {
console.log('window will-download handler 2')
}
当 setTimeout
运行时,我看到以下 console.log()
消息:
trigger window 1 download
window will-download handler 1
window will-download handler 2
从日志中可以看出,will-download事件触发了windows
两者的事件处理程序
如果我为每个 window 指定一个单独的分区,共享事件处理程序的问题得到解决,但我遇到了上面提到的第二个问题 - link 关联在启动时弹出
window1 = new electron.BrowserWindow({
webPreferences: {
partition: 'partition1',
}
})
window2 = new electron.BrowserWindow({
webPreferences: {
partition: 'partition2',
}
})
我明白了。如果这样做有误,请有人告诉我。
这是我修复它的方法:
修复问题 #1:
为 window 设置自定义分区名称,因此它使用自己的 webContents.session
而不是共享默认分区。
主要流程:
windows.quickViewWindow = new electron.BrowserWindow({
...
webPreferences: {
partition: 'quickView',
...
windows.quickViewWindow.webContents.session.once(
'will-download',
(event, item, webContents) => {
event.preventDefault()
...
}
)
quickViewWindow.html:
ipcRenderer.on('load:webview', (event, data) => {
...
webviewNode.setAttribute('partition', 'quickView')
修复问题 #2:
在 window URL 的生产路径中设置 file://
协议:
productionPath = `file://${__static}/quickViewWindow.html`
我有一个 Electron file manager app,它为不同的目的创建了 2 windows:
quickView
用于预览本地文件的渲染器 window。它使用“will-download”侦听器通过阻止下载来检测不支持的文件。main
主渲染器 window。它使用“will-download”侦听器来下载文件。
每个都有自己的 will-download
听众附加到他们的会话。但由于某种原因,quickView
监听器覆盖了 main
监听器。
Window 1
在下一行中,我正在为“主”进程创建一个 will-download
侦听器。此侦听器的目的是下载文件:
win.webContents.session.on('will-download', listener)
下一行中的windows.main
参数是上一行中的win
引用:
const resultInfo = await downloadManager.download(windows.main, {
Window 2
在下一行中,我正在为“quickView”window 创建一个 will-download
侦听器。此侦听器的目的是检测不支持的文件(在 Chromium 中触发下载事件)并阻止下载事件:
windows.quickViewWindow.webContents.session.once('will-download', _willDownloadHandler)
我还没有找到另一种方法来检测不受支持的文件,这就是我首先使用 will-download
事件的原因。
问题
出于某种原因,quickView
window 的 will-download
处理程序覆盖了 main
的处理程序:
当我在这里触发应用更新下载事件时(来自main
进程):
const resultInfo = await downloadManager.download(windows.main, {
它触发 quickView
渲染器的事件处理程序 window:
function _willDownloadHandler (event, item, webContents) {
...
windows.main.webContents.send('load:webview::failed', {path: fileURL})
部分修复
我通过为 quickView
window 的会话指定自定义分区名称,部分解决了 this commit 中的问题,因此它不使用默认会话,也不覆盖由 main
:
will-download
侦听器
主要流程:
windows.quickViewWindow = new electron.BrowserWindow({
...
webPreferences: {
partition: 'quickPreview',
...
windows.quickViewWindow.webContents.session.once(
'will-download',
(event, item, webContents) => {
event.preventDefault()
...
}
)
quickViewWindow.html:
ipcRenderer.on('load:webview', (event, data) => {
...
webviewNode.setAttribute('partition', 'quickPreview')
但是这个修复导致了另一个问题:
快速查看 window 在生产构建中停止工作(可能与协议不适用于非默认会话分区有关)
将自定义分区设置为 webview 会导致 Windows 协议 link 关联在创建包含此 webview 的 window 时在生产中弹出:
我认为这可能是由 electron-builder-plugin 创建的自定义 app://
协议引起的。弹出窗口似乎是由“应用程序”触发的 link.
或者可能是因为我在这条线附近的某处创建 window 时错误地设置了协议:
重现:
- 下载项目
git clone https://github.com/aleksey-hoffman/sigma-file-manager.git
cd sigma-file-manager
npm install
git checkout 47ce65b
npm run electron:build
- 安装来自
./dist_electron
的内置应用
- 在应用程序启动期间,您可以看到弹出窗口
备注:
我刚刚回滚了 47ce65b 提交并添加了一些测试值 所以更容易调试
要切换到最新提交并创建生产版本:
git checkout 5246252
npm run electron:build
electronMain.js
里面的所有console.log()
都显示在终端(命令行)window(不是开发者工具控制台)
要触发快速查看功能:
- Select 导航器页面上任何支持的文件(图像/文本/等)
- 按 Space(应该会打开快速视图 window)
要触发下载事件,您只需打开“导航器”页面并从互联网上拖放任何文件(或网站 URL)即可。它会触发错误的 will-download 事件处理程序(quickView window 的处理程序),您应该会看到控制台消息。
包含此 Web 视图的快速视图 window 是在 app.ready
事件上创建的。指定分区时,将在创建 quickView window 后立即弹出:
更新:
较小的复制示例:
我能够用这段代码重现它:
let window1 = null
let window2 = null
electron.app.on('ready', async () => {
createWindow1()
createWindow2()
setTimeout(() => {
console.log('trigger window 1 download')
window1.webContents.downloadURL('https://whosebug.com')
}, 1000)
})
function createWindow2 () {
window1.webContents.session.once('will-download', downloadHandler1)
window2.webContents.session.once('will-download', downloadHandler2)
}
function createWindow1 () {
window1 = new electron.BrowserWindow()
window1.loadURL('app://./quickViewWindow.html')
window1.webContents.session.once('will-download', downloadHandler1)
}
function createWindow2 () {
window2 = new electron.BrowserWindow()
window2.loadURL('app://./quickViewWindow.html')
window2.webContents.session.once('will-download', downloadHandler2)
}
function downloadHandler1 (event, item, webContents) {
console.log('window will-download handler 1')
}
function downloadHandler2 (event, item, webContents) {
console.log('window will-download handler 2')
}
当 setTimeout
运行时,我看到以下 console.log()
消息:
trigger window 1 download
window will-download handler 1
window will-download handler 2
从日志中可以看出,will-download事件触发了windows
两者的事件处理程序如果我为每个 window 指定一个单独的分区,共享事件处理程序的问题得到解决,但我遇到了上面提到的第二个问题 - link 关联在启动时弹出
window1 = new electron.BrowserWindow({
webPreferences: {
partition: 'partition1',
}
})
window2 = new electron.BrowserWindow({
webPreferences: {
partition: 'partition2',
}
})
我明白了。如果这样做有误,请有人告诉我。
这是我修复它的方法:
修复问题 #1:
为 window 设置自定义分区名称,因此它使用自己的 webContents.session
而不是共享默认分区。
主要流程:
windows.quickViewWindow = new electron.BrowserWindow({
...
webPreferences: {
partition: 'quickView',
...
windows.quickViewWindow.webContents.session.once(
'will-download',
(event, item, webContents) => {
event.preventDefault()
...
}
)
quickViewWindow.html:
ipcRenderer.on('load:webview', (event, data) => {
...
webviewNode.setAttribute('partition', 'quickView')
修复问题 #2:
在 window URL 的生产路径中设置 file://
协议:
productionPath = `file://${__static}/quickViewWindow.html`