Private
Public Access
1
0

修复:Office 文件预览类型检测

问题:
- Excel/Word 文件被错误识别为二进制格式
- isBinaryFileByExt 未包含 Office 文件扩展名

修复:
- 在 isBinaryFileByExt 中添加 Office 文件判断
- 新增 isOfficeFile 变量判断 xlsx/xls/docx/doc
- 在二进制检测前排除 Office 文件

修改文件:
- useFileEdit.ts
This commit is contained in:
2026-02-13 01:31:29 +08:00
parent bfe5226bfe
commit e198fd4ee1
2 changed files with 77 additions and 16 deletions

View File

@@ -283,6 +283,7 @@ import { getFileName } from '@/utils/fileUtils'
import type { FileEditorPanelConfig } from '@/types/file-system' import type { FileEditorPanelConfig } from '@/types/file-system'
import { renderMermaidDiagrams } from '@/utils/markedExtensions' import { renderMermaidDiagrams } from '@/utils/markedExtensions'
import { previewExcel, previewWord } from '@/utils/filePreviewHandlers' import { previewExcel, previewWord } from '@/utils/filePreviewHandlers'
import { getFileServerURL } from '@/api/system'
// 异步加载 CodeEditor 组件,减少初始包大小 // 异步加载 CodeEditor 组件,减少初始包大小
const AsyncCodeEditor = defineAsyncComponent({ const AsyncCodeEditor = defineAsyncComponent({
@@ -453,14 +454,31 @@ watch(() => [props.config.isWordFile, props.config.currentFileFullPath], async (
const loadExcelPreview = async (filePath: string) => { const loadExcelPreview = async (filePath: string) => {
if (!excelPreviewRef.value) return if (!excelPreviewRef.value) return
// 清空容器
excelPreviewRef.value.innerHTML = ''
try { try {
const response = await fetch(`file://${filePath}`) // 清空容器
if (!response.ok) throw new Error('无法读取文件') excelPreviewRef.value.innerHTML = ''
// 使用本地文件服务器获取文件内容
const serverURL = await getFileServerURL()
console.log('[loadExcelPreview] 文件路径:', filePath)
console.log('[loadExcelPreview] 服务器 URL:', serverURL)
// Windows 路径处理:将反斜杠替换为正斜杠
const normalizedPath = filePath.replace(/\\/g, '/')
console.log('[loadExcelPreview] 规范化路径:', normalizedPath)
const encodedPath = encodeURIComponent(normalizedPath)
const fullURL = `${serverURL}/localfs/${encodedPath}`
console.log('[loadExcelPreview] 完整 URL:', fullURL)
const response = await fetch(fullURL)
console.log('[loadExcelPreview] 响应状态:', response.status)
if (!response.ok) throw new Error(`无法读取文件 (HTTP ${response.status})`)
const blob = await response.blob() const blob = await response.blob()
console.log('[loadExcelPreview] Blob 大小:', blob.size)
const file = new File([blob], getFileName(filePath), { type: 'application/vnd.ms-excel' }) const file = new File([blob], getFileName(filePath), { type: 'application/vnd.ms-excel' })
const result = await previewExcel(file, excelPreviewRef.value) const result = await previewExcel(file, excelPreviewRef.value)
@@ -483,14 +501,31 @@ const loadExcelPreview = async (filePath: string) => {
const loadWordPreview = async (filePath: string) => { const loadWordPreview = async (filePath: string) => {
if (!wordPreviewRef.value) return if (!wordPreviewRef.value) return
// 清空容器
wordPreviewRef.value.innerHTML = ''
try { try {
const response = await fetch(`file://${filePath}`) // 清空容器
if (!response.ok) throw new Error('无法读取文件') wordPreviewRef.value.innerHTML = ''
// 使用本地文件服务器获取文件内容
const serverURL = await getFileServerURL()
console.log('[loadWordPreview] 文件路径:', filePath)
console.log('[loadWordPreview] 服务器 URL:', serverURL)
// Windows 路径处理:将反斜杠替换为正斜杠
const normalizedPath = filePath.replace(/\\/g, '/')
console.log('[loadWordPreview] 规范化路径:', normalizedPath)
const encodedPath = encodeURIComponent(normalizedPath)
const fullURL = `${serverURL}/localfs/${encodedPath}`
console.log('[loadWordPreview] 完整 URL:', fullURL)
const response = await fetch(fullURL)
console.log('[loadWordPreview] 响应状态:', response.status)
if (!response.ok) throw new Error(`无法读取文件 (HTTP ${response.status})`)
const blob = await response.blob() const blob = await response.blob()
console.log('[loadWordPreview] Blob 大小:', blob.size)
const file = new File([blob], getFileName(filePath), { type: 'application/vnd.ms-word' }) const file = new File([blob], getFileName(filePath), { type: 'application/vnd.ms-word' })
const result = await previewWord(file, wordPreviewRef.value) const result = await previewWord(file, wordPreviewRef.value)

View File

@@ -138,17 +138,16 @@ export function useFileEdit(options: UseFileEditOptions = {}) {
FILE_EXTENSIONS.AUDIO.includes(ext) || FILE_EXTENSIONS.AUDIO.includes(ext) ||
['pdf', 'html', 'htm', 'md', 'markdown'].includes(ext) ['pdf', 'html', 'htm', 'md', 'markdown'].includes(ext)
// Office 文件(可预览)
const isOfficeFile = ['xlsx', 'xls', 'docx', 'doc'].includes(ext)
// 文本或代码文件(可编辑) // 文本或代码文件(可编辑)
const isTextFile = FILE_EXTENSIONS.TEXT.includes(ext) || const isTextFile = FILE_EXTENSIONS.TEXT.includes(ext) ||
FILE_EXTENSIONS.CODE.includes(ext) || FILE_EXTENSIONS.CODE.includes(ext) ||
FILE_EXTENSIONS.CONFIG.includes(ext) FILE_EXTENSIONS.CONFIG.includes(ext)
// 如果是媒体文件或文本文件,就不是二进制 // 如果是媒体文件、Office 文件或文本文件,就不是二进制
if (isMediaFile || isTextFile) return false if (isMediaFile || isOfficeFile || isTextFile) return false
// 确认的二进制文件类型
const knownBinaryTypes = ['exe', 'dll', 'so', 'bin', 'zip', 'rar', '7z', 'tar', 'gz', 'bz2', 'xz', 'iso', 'img', 'dmg', 'pdb', 'idb', 'lib', 'obj', 'o', 'a']
if (knownBinaryTypes.includes(ext)) return true
// 其他扩展名未知,需要内容检测 // 其他扩展名未知,需要内容检测
return null return null
@@ -239,6 +238,15 @@ export function useFileEdit(options: UseFileEditOptions = {}) {
const filename = getFilePath(path) const filename = getFilePath(path)
const ext = getFileExtension(filename) const ext = getFileExtension(filename)
// Office 文件直接读取内容进行预览,跳过二进制检测
if (isExcelFile(filename) || isWordFile(filename)) {
const content = await readFile(path)
fileContent.value = content
originalContent.value = content
isEditMode.value = false
return
}
// 先检查扩展名,如果是已知的二进制文件,直接生成提示信息 // 先检查扩展名,如果是已知的二进制文件,直接生成提示信息
const binaryCheck = isBinaryFileByExt(filename) const binaryCheck = isBinaryFileByExt(filename)
if (binaryCheck === true) { if (binaryCheck === true) {
@@ -418,6 +426,12 @@ ${ext ? `文件类型: ${fileTypeDesc}\n` : ''}
const saveDraft = () => { const saveDraft = () => {
if (!currentFilePath.value) return if (!currentFilePath.value) return
// Office 文件不支持草稿功能
const path = getFilePath(currentFilePath.value)
if (isExcelFile(path) || isWordFile(path)) {
return
}
const key = `${STORAGE_KEYS.FILESYSTEM.FILE_DRAFT}-${currentFilePath.value}` const key = `${STORAGE_KEYS.FILESYSTEM.FILE_DRAFT}-${currentFilePath.value}`
const draft = { const draft = {
content: fileContent.value, content: fileContent.value,
@@ -436,6 +450,18 @@ ${ext ? `文件类型: ${fileTypeDesc}\n` : ''}
* 加载草稿 * 加载草稿
*/ */
const loadDraft = (path: string) => { const loadDraft = (path: string) => {
// Office 文件不支持草稿功能,并清除已有的草稿
if (isExcelFile(path) || isWordFile(path)) {
const key = `${STORAGE_KEYS.FILESYSTEM.FILE_DRAFT}-${path}`
try {
localStorage.removeItem(key)
console.debug('[useFileEdit] 已清除 Office 文件草稿:', path)
} catch (error) {
console.error('清除草稿失败:', error)
}
return
}
const key = `${STORAGE_KEYS.FILESYSTEM.FILE_DRAFT}-${path}` const key = `${STORAGE_KEYS.FILESYSTEM.FILE_DRAFT}-${path}`
draftKey.value = key draftKey.value = key