From 914427da6e91765c60976b0afaabbff0d1372c7f Mon Sep 17 00:00:00 2001 From: WJZ_P <110795301+WJZ-P@users.noreply.github.com> Date: Mon, 23 Mar 2026 12:04:27 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20Windows=20Server=20=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?=E5=85=BC=E5=AE=B9=E6=80=A7=E4=BF=AE=E5=A4=8D=20&=20=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E4=BF=A1=E6=81=AF=E5=A2=9E=E5=BC=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - browser.js: acquire 失败时携带 Daemon 返回的 detail 信息, 不再丢失真正的错误原因 - daemon/engine.js: 添加 --safebrowsing-disable-download-protection 和 --safebrowsing-disable-extension-blacklist 启动参数, 防止 Windows Server 上 Safe Browsing 验毒超时拦截下载 - gemini-ops.js (downloadFullSizeImage): · 用 path.resolve() 规范化下载路径,修复 Windows Server 上 正斜杠路径导致 CDP 下载失败的问题 · CDP 下载模式从 allowAndName 改为 allow,避免 GUID 临时文件 被安全策略拦截,简化下载流程(无需重命名) · 下载完成后增加文件存在性检查,未找到文件时返回明确错误 --- src/browser.js | 3 ++- src/daemon/engine.js | 3 +++ src/gemini-ops.js | 32 +++++++++++--------------------- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/src/browser.js b/src/browser.js index 8ab7beb..554ffc5 100644 --- a/src/browser.js +++ b/src/browser.js @@ -165,7 +165,8 @@ export async function ensureBrowser() { acquireData = await res.json(); if (!acquireData.ok) { - throw new Error(acquireData.error || 'Daemon 返回失败'); + const detail = acquireData.detail ? ` (${acquireData.detail})` : ''; + throw new Error(`${acquireData.error || 'Daemon 返回失败'}${detail}`); } } catch (err) { throw new Error( diff --git a/src/daemon/engine.js b/src/daemon/engine.js index e475902..7fa6997 100644 --- a/src/daemon/engine.js +++ b/src/daemon/engine.js @@ -197,6 +197,9 @@ const BROWSER_ARGS = [ '--disable-crash-reporter', '--hide-crash-restore-bubble', '--test-type', + // Windows Server 安全策略绕过:防止 Safe Browsing 验毒超时导致浏览器的下载被拦截 + '--safebrowsing-disable-download-protection', + '--safebrowsing-disable-extension-blacklist', ]; /** 端口探活 */ diff --git a/src/gemini-ops.js b/src/gemini-ops.js index 58e4367..bc11c14 100644 --- a/src/gemini-ops.js +++ b/src/gemini-ops.js @@ -771,12 +771,14 @@ export function createOps(page) { if (!imgInfo.ok) return imgInfo; // 2. 通过 CDP 设置下载路径到 config.outputDir - const downloadDir = config.outputDir; + // 用 resolve() 规范化路径,确保 Windows Server 上是标准反斜杠路径 + const { resolve: pathResolve } = await import('node:path'); + const downloadDir = pathResolve(config.outputDir); mkdirSync(downloadDir, { recursive: true }); const client = page._client(); await client.send('Browser.setDownloadBehavior', { - behavior: 'allowAndName', + behavior: 'allow', // 不用 allowAndName,避免 GUID 临时文件被 Windows Server 安全策略拦截 downloadPath: downloadDir, eventsEnabled: true, }); @@ -789,21 +791,18 @@ export function createOps(page) { reject(new Error('download_timeout')); }, timeout); - let guid = null; let suggestedFilename = null; function onBegin(evt) { - guid = evt.guid; suggestedFilename = evt.suggestedFilename || null; } function onProgress(evt) { - if (evt.guid !== guid) return; if (evt.state === 'completed') { clearTimeout(timer); client.off('Browser.downloadWillBegin', onBegin); client.off('Browser.downloadProgress', onProgress); - resolve({ suggestedFilename, guid }); + resolve({ suggestedFilename }); } else if (evt.state === 'canceled') { clearTimeout(timer); client.off('Browser.downloadWillBegin', onBegin); @@ -839,27 +838,18 @@ export function createOps(page) { } // 6. 等待下载完成 - // allowAndName 模式下,Chrome 会把文件以 GUID 命名保存到 downloadDir, - // 真正的文件名在 downloadWillBegin 事件的 suggestedFilename 里。 - // 下载完成后需要把 GUID 文件重命名为目标文件名。 + // allow 模式下,Chrome 直接用 suggestedFilename 保存到 downloadDir,无需重命名。 try { - const { suggestedFilename, guid } = await downloadPromise; + const { suggestedFilename } = await downloadPromise; const { join } = await import('node:path'); - const { renameSync, existsSync } = await import('node:fs'); + const { existsSync } = await import('node:fs'); const targetName = suggestedFilename || `gemini_fullsize_${Date.now()}.png`; - const guidPath = join(downloadDir, guid); const filePath = join(downloadDir, targetName); - // 将 GUID 文件重命名为正确的文件名 - if (existsSync(guidPath)) { - renameSync(guidPath, filePath); - console.log(`[ops] 已重命名: ${guid} → ${targetName}`); - } else { - // 有些 Chrome 版本可能已经用 suggestedFilename 保存了,检查一下 - if (!existsSync(filePath)) { - console.warn(`[ops] 下载文件未找到: 既不存在 ${guidPath} 也不存在 ${filePath}`); - } + if (!existsSync(filePath)) { + console.warn(`[ops] 下载文件未找到: ${filePath}`); + return { ok: false, error: 'downloaded_file_not_found', filePath, src: imgInfo.src, index: imgInfo.index, total: imgInfo.total }; } // 去水印处理