javascript - Electron.js:如何为一个窗口创建一个单独的下载 webContents.session?
问题描述
我有一个 Electron文件管理器应用程序,它为不同目的创建了 2 个窗口:
quickView
用于预览本地文件的渲染器窗口。它使用“will-download”侦听器通过阻止下载来检测不受支持的文件。main
主渲染器窗口。它使用“will-download”监听器来下载文件。
每个人都有自己的will-download
听众附加到他们的会话中。但是由于某种原因,quickView
监听器覆盖了main
监听器。
窗口 1
在以下行中,我正在will-download
为“主”进程创建一个侦听器。这个监听器的目的是下载文件:
win.webContents.session.on('will-download', listener)
下一行中的windows.main
参数是上行中的win
引用:
const resultInfo = await downloadManager.download(windows.main, {
窗口 2
在以下行中,我正在will-download
为“quickView”窗口创建一个侦听器。此侦听器的目的是检测不受支持的文件(在 Chromium 中触发下载事件)并阻止下载事件:
windows.quickViewWindow.webContents.session.once('will-download', _willDownloadHandler)
我还没有找到另一种方法来检测不受支持的文件,这就是我will-download
首先使用事件的原因。
问题
由于某种原因,will-download
窗口quickView
的处理程序会覆盖以下处理程序main
:
当我在此处触发应用程序更新下载事件时(来自main
流程):
const resultInfo = await downloadManager.download(windows.main, {
quickView
它触发渲染器窗口的事件处理程序:
function _willDownloadHandler (event, item, webContents) {
...
windows.main.webContents.send('load:webview::failed', {path: fileURL})
部分修复
我通过为窗口会话指定自定义分区名称部分解决了此提交quickView
中的问题,因此它不使用默认会话并且不覆盖由以下will-download
创建的侦听器main
:
主要工艺:
windows.quickViewWindow = new electron.BrowserWindow({
...
webPreferences: {
partition: 'quickPreview',
...
windows.quickViewWindow.webContents.session.once(
'will-download',
(event, item, webContents) => {
event.preventDefault()
...
}
)
快速视图窗口.html:
ipcRenderer.on('load:webview', (event, data) => {
...
webviewNode.setAttribute('partition', 'quickPreview')
但是这个修复导致了另一个问题:
快速查看窗口在生产构建中停止工作(可能与协议不使用非默认会话分区有关)
将自定义分区设置为 webview 会导致在创建包含此 webview 的窗口时在生产中弹出 Windows 协议链接关联:
我认为这可能是由electron-builder-pluginapp://
创建的自定义协议引起的。似乎弹出窗口是由“应用程序”链接触发的。
或者它正在发生,因为当我在这条线附近的某处创建窗口时,我错误地设置了协议:
重现:
- 下载项目
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
所有console.log()
里面electronMain.js
都显示在终端(命令行)窗口(不是开发者工具控制台)中。
要触发快速查看功能:
- 在导航器页面上选择任何支持的文件(图像/文本/等)
- 按空格键(应打开快速查看窗口)
要触发下载事件,您只需打开“导航器”页面并从 Internet 拖放任何文件(或网站 URL)即可。它将触发错误的 will-download 事件处理程序(quickView 窗口的处理程序),您应该会看到控制台消息。
包含此 web 视图的 quickView 窗口是在app.ready
事件中创建的。指定分区后,在创建快速查看窗口后会立即出现弹出窗口:
更新:
较小的复制示例:
我能够用这段代码重现它:
let window1 = null
let window2 = null
electron.app.on('ready', async () => {
createWindow1()
createWindow2()
setTimeout(() => {
console.log('trigger window 1 download')
window1.webContents.downloadURL('https://stackoverflow.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 事件触发了两个窗口的事件处理程序
如果我为每个窗口指定一个单独的分区,共享事件处理程序的问题得到解决,但我得到了上面提到的第二个问题 - 链接关联在启动时弹出
window1 = new electron.BrowserWindow({
webPreferences: {
partition: 'partition1',
}
})
window2 = new electron.BrowserWindow({
webPreferences: {
partition: 'partition2',
}
})
解决方案
我想到了。如果这是错误的方法,请告诉我。
这是我修复它的方法:
修复问题 #1:
为窗口设置一个自定义分区名称,因此它使用自己的webContents.session
而不是共享默认分区名称。
主要工艺:
windows.quickViewWindow = new electron.BrowserWindow({
...
webPreferences: {
partition: 'quickView',
...
windows.quickViewWindow.webContents.session.once(
'will-download',
(event, item, webContents) => {
event.preventDefault()
...
}
)
快速视图窗口.html:
ipcRenderer.on('load:webview', (event, data) => {
...
webviewNode.setAttribute('partition', 'quickView')
修复问题 #2:
file://
在窗口 URL 的生产路径中设置协议:
productionPath = `file://${__static}/quickViewWindow.html`
推荐阅读
- reveal.js - Reveal.js 在图像上显示水平线
- java - 我不知道为什么我的 springboot 应用程序无法查询数据库
- reactjs - 无法在 Reactjs 中暂停音频
- jmeter - 如何从 Jmeter 中的子采样器请求中提取值
- python - 由于图像增强或噪声而欠拟合?
- r - 仅突出显示标记的值
- php - 模型 [App\Product] 没有查询结果,同时从表 laravel 7 中获取所有数据
- docker - K8S - Docker - ARM unbutu 64 位 - qemu:未捕获的目标信号 11(分段错误) - 核心转储
- python-3.x - 什么可能导致我的代码给出错误的答案?
- apache-flink - 如何在 Flink 的 HiveCatalog 中添加分区位置?