最近在一个 Vue 3 + Vite 的 OA 附件页里,我重新走了一遍 DOCX、XLSX、PPTX 和 PDF 的接入链路。开发环境只有一个目标:点附件后在当前页面预览;生产环境却多了三个硬约束:文件接口需要鉴权、站点部署在 /oa/ 子路径、运行时不能访问公网 CDN。
这类需求真正容易出错的地方并不是组件标签,而是文件怎么进入组件、Worker/WASM 从哪里加载,以及构建产物是否把整条预览链路一起交付。
本文给出一套可复现的 Vue 3 落地方法。示例以 2026-08-05 核验的 File Viewer v2.2.5 为基线;我在维护 File Viewer,但下面关于 URL、Blob、Range 和静态资源版本一致性的判断,同样适用于其他浏览器预览方案。
文件来源通常只有两类:可以直接访问的 URL,或者业务已经拿到的 File/Blob。
公开 URL、同源 Cookie 接口、带短期签名的对象存储地址,可以直接交给预览组件。需要自定义鉴权头、解密或统一处理 401 的接口,应该由业务层完成下载,再把二进制包装为带正确扩展名的 File。
先用 Full 包跑通完整链路:
bash代码解读复制代码pnpm add @file-viewer/vue3-full pnpm add -D @file-viewer/vite-plugin
vue代码解读复制代码<script setup> import { ref } from 'vue' import { FileViewer, type ViewerOptions }
from '@file-viewer/vue3-full' const selected = ref<File>() const options: ViewerOptions = { theme: '
light', styleIsolation: 'auto', toolbar: { position: 'bottom-right' } }
function openLocalFile(event: Event) { const input = event.target as HTMLInputElement
selected.value = input.files?.[0] } </script> <template> <input type="file"
accept=".docx,.xlsx,.pptx,.pdf" @change="openLocalFile" > <FileViewer
v-if="selected" :file="selected" :options="options" /> </template>
<style scoped> .viewer { display: block; height: min(760px, 78vh); } </style>Full 包已经带完整 preset,不要再次安装并注入同一套 renderer。只有文件类型明确、体积预算经过测量后,再考虑按能力拆包。
本地能打开、部署后白屏,最常见的原因不是 Vue 组件失效,而是只发布了 JavaScript 入口,没有发布解析器运行时。
Vite 配置需要复制同版本的 Worker、WASM、字体和 vendor 资源:
ts代码解读复制代码// vite.config.ts import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue' import { fileViewerRenderers } from '@file-viewer/vite-plugin'
export default defineConfig({ base: '/oa/', plugins: [ vue(),
fileViewerRenderers({ copyAssets: true }) ] })
默认资源地址是部署基址下的 file-viewer/。站点基址是 /oa/ 时,应在生产 Network 面板里看到 /oa/file-viewer/...,而不是根路径 /file-viewer/... 或公共 CDN。
如果资产统一放在独立静态目录,可以显式设置:
ts代码解读复制代码import { setDefaultFullAssetBaseUrl } from '@file-viewer/vue3-full'
setDefaultFullAssetBaseUrl('/static/file-viewer/')非 Vite 项目可以在构建阶段复制同版本资源:
bash代码解读复制代码npx --no-install file-viewer-copy-assets ./public/file-viewer
不要从另一版本的部署目录手工拷贝 WASM。组件、Worker 和 vendor 资源版本不一致时,业务层往往只能看到模糊的加载失败或空白页。
自定义 Header 不应该塞进预览器的每条内部请求。让业务请求层负责鉴权、重试和审计,预览器只接收已经授权的二进制,边界更清楚。
vue代码解读复制代码<script setup> import { ref } from 'vue' import { FileViewer } from '@file-viewer/
vue3-full' const previewFile = ref<File>() const errorMessage = ref('') async function
openAttachment(id: string, filename: string) { errorMessage.value = '' const response = await
fetch(`/api/attachments/${id}`, { credentials: 'include', headers: { 'X-Preview-Request': '1'
} }) if (!response.ok) { errorMessage.value = `附件读取失败:${response.status}`
return } const blob = await response.blob() previewFile.value = new File([blob], filename,
{ type: blob.type, lastModified: Date.now() }) } </script> <template>
<button @click="openAttachment('42', '合同.docx')"> 预览合同 </button>
<p v-if="errorMessage">{{ errorMessage }}</p> <FileViewer v-if="previewFile" :file="previewFile" />
</template>
文件名不能随意丢掉。很多容器格式的 MIME 都不够稳定,正确扩展名仍是选择预览链路的重要依据。
这条方案也有明确代价:fetch + Blob 通常要等完整下载,并在浏览器内存中保留一份二进制。对超大 PDF,如果服务端支持同源 Range 请求,直接 URL 更适合渐进读取;需要强制自定义鉴权头时,则要在流式能力、内存和安全边界之间做取舍。
DOCX、XLSX、PPTX、PDF 最终进入同一个组件,不代表底层是同一个解析器。
DOCX 需要处理 OpenXML 关系、样式、图片、字体和分批渲染。
XLSX 重点是工作表、合并单元格、样式和大表格 Worker。
PPTX 涉及幻灯片关系、主题、图片以及独立 Worker。
PDF 由 PDF.js 链路处理,服务端支持 Range 才有条件渐进读取。
发布日验证结果为:208 个已注册扩展名映射到 25 条预览链路。这里描述的是扩展名路由矩阵,不是 208 套独立渲染器,也不代表所有文件都能像素级还原。

本文的 PowerPoint 范围只包含 .pptx,不展开旧版 .ppt。
我会固定检查下面五项,而不是只看开发服务器有没有报错:
使用真实 base 执行 build 和 preview,在 /oa/ 下打开页面。
用 DOCX、XLSX、PPTX、PDF 各一个脱敏样本检查 Worker、WASM、字体和 vendor 请求,确认没有 404。
同时验证 URL 与 File 两条输入,覆盖 401、CORS、Range、下载中断和快速切换附件。
验证内容而非首屏:Word 看页眉页脚和表格,Excel 看合并单元格和大表滚动,PPTX 看页序与图片,PDF 看目录、旋转页和打印。
断开公网再次测试,确认所有运行时资源都来自自己的网络。
最后还要记录浏览器版本、设备内存、文件大小、页数和峰值内存。没有这些条件,“大文件可用”没有可比较意义。
浏览器本地预览适合文件已有业务权限、团队希望减少额外副本,并愿意把运行时资产和兼容性测试纳入前端交付的场景。
如果需要像素级统一输出、服务器全文检索、归档 PDF、病毒扫描或集中水印,服务端转码通常更合适。公开低敏文件且团队不想维护运行时,可以直接评估成熟 SaaS。需要编辑、批注协同或复杂公式重算时,应选 Office、CAD 或专业编辑器,而不是把只读预览器当成编辑器。
组件标签只是入口。文件输入、运行时版本、鉴权、内存和生产回归能一起闭环,才算真正交付了预览功能。
完整 API 与部署参数见 Vue 3 接入与内网部署文档。
作者:执子念的飞鱼
链接:https://juejin.cn/post/7670065996377112616
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。