File Viewer v2.2.2:从“能预览”到“可交付”的前端文件工作台
做一个 PDF 预览页并不难,难的是把它扩展成能长期维护的文件工作台:Office 新旧格式要分流,工程模型不能依赖公网转换,大文本不能拖垮主线程,Worker/WASM/字体还要跟随应用进入内网。
File Viewer v2.2.2 围绕这几个问题完成了一轮更新。当前支持矩阵收录 208 个不重复扩展名、25 条 renderer 预览链路、54 个 npm 发布目标,并提供 Web、Vue 3、Vue 2.7、Vue 2.6、React、React legacy、Svelte、jQuery 共 8 个 Full 入口。

这篇文章记录新版设计、格式链路和生产部署方式,也说明哪些能力不能被一张“支持”表格过度概括。
一、新设计不是换皮,而是重新整理文件工作流
旧 Demo 更像逐项验证 renderer 的测试页。新版工作台则围绕真实使用过程重新布局:
固定工具栏,文件很长时仍可操作;
预览画布独立滚动,避免外层页面和文档争抢滚动;
样例库按格式族组织,可直接验证真实文件;
保留最近打开,减少重复选择;
支持明暗主题与移动端“更多”入口;
通过
?url=进入沉浸预览,便于从业务系统跳转。

这些调整看起来属于界面,实质上解决的是多格式共存后产生的操作密度问题。用户不应该为了切换文件来源或下载一个长文档,不断回到页面顶部。
二、支持矩阵从“扩展名”落到 renderer

1. 旧 PPT 使用独立二进制链路
.pptx 是 OOXML,.ppt 是复合二进制格式。v2.2.x 中,旧 .ppt 通过 @file-viewer/ppt 进入独立解析流程,并结合 Worker、OffscreenCanvas 和 WASM 生成页面,不再假设它能复用 PPTX 解析器。
2. STEP、IGES、BREP 在本地完成几何转换
STEP/STP、IGES/IGS、BREP 通过 OCCT Worker/WASM 执行真实三角化,再生成 Three.js 网格。装配层级、实例、法线和面颜色会随结构传回主线程,整个过程不需要把文件上传到公共转换服务。
3. 文本与表格按大文件思路处理
代码、日志与大文本使用有界虚拟化;CSV/TSV 处理 UTF-8、GBK、GB18030,并可显示行号。Markdown 遇到大内容时优先维持可读性和交互响应,而不是一次性构建全部 DOM。
4. 压缩包内部文件继续复用统一预览器
ZIP、7Z、RAR、TAR、ISO、APK、CBZ/CBR 等格式先展示目录。用户选择内部文件后再按需解压,并重新进入统一类型识别和 renderer 路由,无需为压缩包维护另一套预览 UI。

三、Vue 3 + Vite 接入
组件包和 Vite 插件应固定为相同版本:
pnpm add @file-viewer/vue3-full@2.2.2
pnpm add -D @file-viewer/vite-plugin@2.2.2
在 vite.config.ts 中启用运行时资源复制:
import { fileViewerRenderers } from '@file-viewer/vite-plugin'
import vue from '@vitejs/plugin-vue'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
vue(),
fileViewerRenderers({
copyAssets: true
})
]
})
页面里使用 Full 入口:
<script setup lang="ts">
import FileViewer from '@file-viewer/vue3-full'
</script>
<template>
<FileViewer
url="/files/design-review.step"
style="height: 720px"
/>
</template>
如果下载接口需要鉴权,建议先获取 Blob,再包装为带可信文件名的 File。扩展名是 renderer 路由的重要依据,不能把 /api/file/42/download 之类没有后缀的接口地址当作文件类型。
const response = await fetch('/api/files/42/download', {
headers: {
Authorization: `Bearer ${token}`
}
})
const blob = await response.blob()
const file = new File([blob], 'design-review.step', {
type: blob.type
})
四、非 Vite 与私有化环境怎样部署
Webpack、Rspack、Rollup、Vue CLI 或 Umi 项目需要显式复制 Full 包对应版本的运行时资源:
npx --no-install file-viewer-copy-assets ./public/file-viewer
如果静态目录不是默认的 /file-viewer/,在应用启动时覆盖资产基址:
import { setDefaultFullAssetBaseUrl } from '@file-viewer/vue3-full'
setDefaultFullAssetBaseUrl('/static/file-viewer/')

完整交付物不只有组件 JavaScript,还包括 PDF、DOCX、Spreadsheet、PPT/PPTX、CAD/OCCT 等 Worker,相关 WASM、CJK 字体,以及 Typst、Archive、Draw.io、SQLite 等 vendor 资源。
部署到 Nginx 时还要确认:
.mjs返回application/javascript;Worker/WASM 请求没有被 SPA 的 HTML fallback 接管;
子路径部署后的资源基址正确;
组件、插件和静态资产版本一致;
CSP 允许应用所需的 Worker 和 WASM 加载方式。
五、这次更新修复了哪些生产问题
v2.2.x 还处理了几类不太显眼、但会直接影响交付的问题:
上传 PDF 渲染后再下载,不再因
ArrayBuffer被转移给 PDF.js Worker 而得到 0 字节文件;复杂 DOCX 的 WPS/WPG、图片锚点、嵌套组变换和页面/段落锚点混排得到修复;
PPTX 样式能进入实际 ShadowRoot,组件嵌入 Web Component 时不再丢失样式;
Worker 请求适配子路径,不再默认固定根路径;
PDF 在全宽、flex grow 和外层滚动容器中保持正确居中缩放;
EPUB 引擎改为包内懒加载,并加入安全 XML DOM 与发布审计门禁。
六、能力边界也应该成为产品的一部分
208 个扩展名不代表每一种格式都能达到原生软件的全部保真度。IFC、3DM 等格式仍需按真实能力显示边界;Excel 使用虚拟表格时,不应暴露无法保证完整结果的打印操作;PlantUML 需要配置自托管 SVG 服务。
同样,安装 Full 包也不等于部署完成。只有版本匹配的 Worker、WASM、字体与 vendor 资源都能在目标网络中访问,对应格式链路才算真正可用。
结语
这一轮更新的重点,是把 File Viewer 从格式演示页继续推进为可接入、可验证、可私有化交付的文件工作台。格式数量只是结果,背后更重要的是明确的 renderer 路由、主线程之外的重型解析,以及一套能被持续回归的真实样例。
File Viewer 自研源码与组件包采用 Apache-2.0;完整发行物中的独立运行时和第三方依赖保留各自 LICENSE/NOTICE。
浙公网安备 33010602011771号