「在网页里预览一下这个 Word 文档」——需求听起来很小,实际落地时会发现,没有一个方案是免费又全能的。
下面把常见的几条路和它们各自的代价说清楚。
为什么浏览器原生做不到
PDF 还好,Chrome、Edge、Safari 都内置了 PDF 渲染,一个 <iframe> 就能出图。
Office 三件套不行。.docx / .xlsx / .pptx 本质上是一堆 XML 打成的 zip 包(OOXML),里面描述的是「这段文字用什么字体、在什么位置、什么样式」。浏览器没有 Word 的排版引擎,拿到这些 XML 也不知道该画成什么样。
所以所有方案都在回答同一个问题:谁来做这个排版?
四条路
| 方案 | 排版谁做 | 保真度 | 主要代价 |
|---|---|---|---|
| 第三方在线服务 | 微软/Google 的服务器 | 高 | 文件要传到别人服务器 |
| 服务端转 PDF | 自己服务器上的 LibreOffice | 中高 | 资源开销大、并发差 |
| 前端库直接渲染 | 浏览器里的 JS | 中低 | 复杂样式丢失 |
| 服务端转图片 | 自己服务器 | 高 | 不能选中复制文字 |
第三方在线服务
微软的 Office Online Viewer、Google Docs Viewer,把文件 URL 拼进去就能预览。
实现成本几乎为零,保真度也最高——毕竟是 Office 自己渲染的。
代价很直接:文件必须是公网可访问的 URL,而且会被传到对方服务器。内部文档、用户隐私文件,这条路直接堵死。另外这类服务对文件大小有限制,也不保证可用性——它挂了你就跟着挂。
服务端转 PDF
在自己服务器上装 LibreOffice,用 headless 模式把 Office 文档转成 PDF,前端再按 PDF 预览。
这是可控性和保真度平衡得比较好的方案,文件不出自己的服务器。
代价是资源开销。LibreOffice 启一个转换进程是百毫秒到数秒级,内存占用可观,高并发下必须上队列,否则服务器直接被拖垮。而且它的中文字体依赖是个经典坑——容器里不装中文字体,转出来全是方块。
前端库直接渲染
docx 有 mammoth、docx-preview;xlsx 有 SheetJS;pptx 的库普遍不成熟。
好处是文件完全不离开浏览器,隐私最好,服务器零压力。
代价是保真度。mammoth 的定位本来就是「提取语义结构」而不是「还原排版」——它把 docx 转成干净的 HTML,页边距、分栏、文本框、艺术字、复杂表格合并这些基本都会丢。简单文档看着没问题,格式一复杂就露馅。
SheetJS 社区版能读数据,但单元格样式、条件格式、图表这些要商业版。
服务端转图片
转成一页一张图,前端当图片轮播。
保真度最高,前端实现最简单,兼容性最好。
代价是文字不能选中、不能搜索、不能复制,而且大文档的图片体积很可观。适合只读展示、防复制的场景,不适合需要交互的。
怎么选
不是选一个,多数产品是组合:
- PDF 走浏览器原生,零成本
- 简单 docx 走前端库,快且不占服务器
- 复杂文档和 pptx 走服务端转换
- 对隐私敏感的场景,禁掉第三方服务这条路
判断「简单还是复杂」很难在上传时静态判断,实践中常见的做法是先用前端库试,渲染结果异常或者超时就降级到服务端。
几个一定会踩的坑
中文字体。 服务端转换的容器里不装中文字体,输出必然是方块。这个问题在本地开发环境不会复现,因为开发机上有字体——上线才炸。
老格式。 .doc / .xls / .ppt 是二进制格式,和 OOXML 完全是两回事,多数前端库不支持,只能服务端转。而用户手上的老文件比你以为的多。
加密文档。 带密码的文件所有方案都打不开,得先让用户输密码,而多数库的解密支持很差。
字体替换导致的错版。 文档里用了服务器上没有的字体,转换时会替换成别的,行宽变了,排版就跟着串——尤其是那种精确排版的表格和简历模板。
超大文件。 几百页的 PDF、几万行的 Excel,前端渲染会直接卡死。得做分页加载或虚拟滚动,这部分工作量往往比预览本身还大。
最后
这件事没有银弹。真正要决定的是三个变量的优先级:保真度、隐私、成本。你想要哪两个,就得放弃第三个。
我自己在 forxi.cn 上做了个文件预览,走的是服务端转换那条路——保真度和隐私可控,代价就是并发上不去,得排队。这是选择的结果,不是没做优化。