fix: binary file download fails with 0KB in WebUI mode + add context menu download#1324
Conversation
**Problem:** When downloading Excel/xlsx (and other binary files like PDF, PPT, Word) from the preview panel in WebUI mode, the downloaded file is always 0KB. **Root Cause:** Two compounding issues: 1. When a binary file is opened in the preview panel, `content` is set to an empty string `""` (since binary files cannot be loaded as UTF-8 text). The preview components use `metadata.filePath` instead. The download handler however did `new Blob([content])`, producing an empty 0-byte blob. 2. The naive fix of using `ipcBridge.fs.readFileBuffer` doesn't work in WebUI mode because the WebSocket bridge serializes ArrayBuffer to a UTF-8 string, corrupting binary data. Using `fetch(dataUrl)` on a `data:` URL is also blocked by CSP (`connect-src` does not allow `data:`). **Fix:** Add a dedicated branch in `handleDownload` for binary content types (excel, pdf, ppt, word) when `metadata.filePath` is available: - Use `ipcBridge.fs.getImageBase64` to read the file as a base64-encoded data URL (this IPC already exists, transfers as a plain JSON string, and is safe over WebSocket — no binary corruption). - Decode the base64 in-memory using `atob()` + `Uint8Array` (no `fetch()` call, so no CSP violation). - Create a `Blob` with the correct MIME type for the file extension. This approach works in both Electron desktop and WebUI modes. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Add a "Download" button to the right-click context menu in the workspace file tree, allowing users to download any file directly without going through the preview panel first. This is especially important for binary files (zip, tar.gz, etc.) that cannot be previewed — previously there was no way to download them from the WebUI at all. Even for previewable binary files (xlsx, pdf, etc.), this provides a more direct download path. Implementation: - Add `handleDownloadFile` to `useWorkspaceFileOps` hook, using the same `getImageBase64` + `atob()` approach as the preview panel fix to ensure binary-safe transfer over WebUI's WebSocket bridge. - Add download button to the context menu (visible for all files). - Add i18n translations for all 6 supported locales (en-US, zh-CN, zh-TW, ja-JP, ko-KR, tr-TR). Co-Authored-By: Claude Opus 4.6 <[email protected]>
53f268a to
c7c38e1
Compare
piorpua
left a comment
There was a problem hiding this comment.
Code Review
Verdict: ✅ Approved with follow-up commits
修复方案正确,已在本地跟进以下改进:
Changes Applied
1. Extracted shared base64ToBlob utility (src/renderer/utils/base64.ts)
Moved the duplicated atob decode logic and MIME_MAP into a shared module, eliminating the DRY violation across PreviewPanel.tsx and useWorkspaceFileOps.ts.
export function base64ToBlob(dataUrl: string, mimeType: string): Blob { ... }
export const BINARY_MIME_MAP: Record<string, string> = { xlsx: '...', pdf: '...', ... };2. Fixed MIME type resolution in useWorkspaceFileOps.ts
Changed from regex-extracting the MIME from the data: URL prefix (which returns application/octet-stream for binary files) to extension-based lookup via BINARY_MIME_MAP, consistent with PreviewPanel.tsx.
3. Removed console.error residual (useWorkspaceFileOps.ts:479)
4. Added unit tests (tests/unit/base64.test.ts) — 6 tests, all passing.
The core fix (using getImageBase64 + in-memory atob decode to bypass CSP connect-src) is sound and correctly targets the root cause.
问题描述 / Problem
在 WebUI 模式下,从预览面板下载 Excel/xlsx、PDF、PPT、Word 等二进制文件时,
下载的文件始终为 0KB,无法正常使用。
此外,工作区文件树没有直接下载选项,导致 .zip 等无法预览的二进制文件完全无法下载。
根本原因 / Root Cause
问题一(0KB):
打开二进制文件预览时,程序将
content设为空字符串""(因为二进制无法以 UTF-8 读取),预览依赖
filePath,但下载时执行的是new Blob([content]),content 为空,导致 0 字节文件。问题二(WebSocket binary 损坏):
WebUI 模式下 WebSocket bridge 会把
ArrayBuffer强制转为 UTF-8 字符串,导致
readFileBuffer无法安全传输二进制数据。用
fetch(data: URL)的方案又被 CSP 的connect-src策略拦截。解决方案 / Solution
利用已有的
ipcBridge.fs.getImageBase64接口读取任意文件为 base64 字符串(JSON 字符串传输,对 WebSocket 完全安全),再在浏览器内存中用
atob()+Uint8Array解码为二进制,最后以正确 MIME 类型创建 Blob 触发下载。
此方案在 Electron 桌面端和 WebUI 模式下均可正常工作。
变更内容 / Changes
Commit 1 —
fix: binary file download fails with 0KB in WebUI modePreviewPanel.tsx:为excel / pdf / ppt / word类型增加专用下载分支,通过
getImageBase64+atob()读取文件二进制,用正确 MIME 类型下载Commit 2 —
feat: add download option to workspace file context menuuseWorkspaceFileOps.ts:新增handleDownloadFile方法workspace/index.tsx:右键菜单增加"下载"按钮(对所有文件类型生效,包括 .zip 等)测试 / Testing