vue3-files-preview
| Install | |
|---|---|
npm install vue3-files-preview |
|
| Latest Version: | 1.6.1 |
| Vue: | 3 |
| License: | MIT |
| Last Updated: | Oct 16, 2026 |
| Links: | Gitee · npm |
vue3-files-preview
Vue3 多格式文档 / 模型预览组件。单个 <FilePreview> 按文件类型自动分发到对应查看器,支持本地 File 对象与远程 URL 两种数据源。
支持格式
| 类型 | 扩展名 |
|---|---|
| 3D 模型 | glb / gltf / obj / fbx / stl / ply(含视图立方体 26 方位、模型树楼层/构件显隐、点击拾取/隔离/透明化、漫游、剖切、动画播放、环境光照、截图、网格/坐标轴) |
| CAD 图纸 | dxf(图层面板、图层拾取、距离测量、截图) |
| 文档 | pdf / docx / xlsx / pptx / md / csv / tsv / txt 等(xlsx 支持内嵌图片预览、虚拟滚动;md 提供目录大纲) |
| 媒体 | 常见图片、音频、视频格式(视频默认原生播放;videoPlayer="xgplayer" 时换用西瓜播放器,.flv 与 .m3u8(HLS)经官方引擎全平台可播——原生 <video> 不支持 flv 容器,HLS 的原生支持随浏览器而定(Chrome 146+ / Safari 支持,Firefox 等不支持时给出切换提示)。.avi/.wmv 浏览器与 JS 引擎均无解码器,仅可下载。注意:m3u8 分片按播放列表相对地址拉取,需服务端允许跨域;带鉴权请求头的源会先整体转 blob,相对地址分片将无法解析,此类场景请让分片使用绝对地址) |
| 压缩文件 | zip(左侧条目列表带路径过滤与排序、单条目下载、嵌套压缩包预览、内嵌查看器工具栏由外层顶栏托管) |
旧版二进制格式(.doc / .ppt / .xls)无法在浏览器端解析,会回退到 UnsupportedViewer 并给出「另存为新格式」的补救提示;其余不支持的格式同样回退到 UnsupportedViewer。
安装
npm install vue3-files-preview
yarn add vue3-files-preview
pnpm add vue3-files-preview
本包以 peerDependencies 声明全部运行时依赖(vue 之外还有 docx-preview、exceljs、pdfjs-dist、three、dxf-viewer、mermaid、katex、marked、highlight.js、dompurify、pptx-preview、vue-pdf-embed、jszip、ssf、xgplayer、xgplayer-flv、xgplayer-hls、core-js)。npm 7+ / pnpm / yarn 会自动安装 peer 依赖;如果手动管理依赖,请按需安装上表格式对应的库。其中:
pdfjs-dist与vue-pdf-embed为精确锁定版本(两者必须共享同一个 pdf.js 实例),请勿自行升级;three/dxf-viewer体积较大且仅 3D / DXF 格式用到,宿主若确认不预览这两类格式,可自行省略(对应查看器分包不会被加载);xgplayer/xgplayer-flv/xgplayer-hls/core-js仅视频的第三方播放器模式(videoPlayer="xgplayer")用到,分包按需懒加载;native 模式(默认)不下载对应代码。core-js是 xgplayer 自身声明的依赖。
Vite 插件(必须)
本包依赖 vue-pdf-embed、pdfjs-dist、dxf-viewer 等库,在 Vite 消费时存在预构建兼容、CJS 互操作等问题。请务必在消费项目的 vite.config.ts 中添加内置 Vite 插件:
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import { vue3FilesPreviewPlugin } from "vue3-files-preview/plugin";
export default defineConfig({
plugins: [vue(), vue3FilesPreviewPlugin()]
});
该插件一站式解决以下问题:
| 配置项 | 原因 |
|---|---|
| PDF Worker 自动部署 | 将包内 pdfjs-dist 的 worker 文件自动复制到消费项目的 public/ 目录 |
opentype.js alias |
dxf-viewer 依赖的 opentype.js 是 CJS 格式,自动 resolve 到正确的入口 |
optimizeDeps.include |
vue-pdf-embed、pdfjs-dist、jszip、docx-preview 等库的 ESM 导出方式与 Vite 预构建不兼容,自动强制预构建 |
使用
<template>
<FilePreview :url="fileUrl" style="width: 100%; height: 600px" @close="onClose" />
</template>
<script setup>
import { FilePreview } from "vue3-files-preview";
import "vue3-files-preview/dist/style.css";
const fileUrl = "https://example.com/model.glb";
</script>
本地文件预览:
<FilePreview :file="fileObj" />
单独使用某个查看器
除聚合入口 FilePreview 外,各格式的查看器也可单独按需引入(均为异步组件,用到哪个才加载对应分包):
<template>
<ImageViewer :source="file" file-name="示例.png" />
</template>
<script setup>
import { ImageViewer } from "vue3-files-preview";
import "vue3-files-preview/dist/style.css";
</script>
可单独使用的查看器:ThreeViewer、DxfViewer、ImageViewer、DocumentViewer(纯文本)、MarkdownViewer、DocxViewer、XlsxViewer、CsvViewer、PdfViewer、PptxViewer、AudioViewer、VideoViewer、ArchiveViewer、UnsupportedViewer。
- 公共 props:
source(必填,File对象或 url 字符串)、fileName(可选)、requestHeaders(可选,见「带鉴权的远程文件」一节;传入本地File时查看器内部会自动忽略)。 - 专属 props:
ThreeViewer/UnsupportedViewer需ext(扩展名);PdfViewer支持mode/showModeToggle;PptxViewer支持mode/showPageNav;VideoViewer支持videoPlayer("native"默认 /"xgplayer"西瓜播放器,flv 与 m3u8 仅后者可播);ThreeViewer还支持background/autoRotate/showGrid/showAxis/dracoDecoderPath。注意ThreeViewer单独使用时自身的默认值与FilePreview聚合入口不同:showGrid为true、background为#171717(聚合入口由容器统一下发,故showGrid默认false、背景随主题令牌)。 - 事件:
loaded/error照常触发(3D、DXF 另有progress)。 - 上下文:单独使用时不会注入
FilePreview的上下文,顶栏的保存 / 关闭 / 主题按钮会自动隐藏,不影响核心预览。
Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| url | string |
"" |
远程文件地址,与 file 二选一 |
| file | File | null |
null |
本地文件对象;与 url 同时存在时 file 优先 |
| type | string |
"" |
强制指定文件扩展名(不含点,如 glb/docx),用于 url 无扩展名或扩展名与实际格式不符的场景;缺省时从文件名推断 |
| background | string |
随主题 | 3D 场景背景色;默认读取主题令牌(深色 #171717 / 浅色 #f8f8f8),显式传入后固定为该值 |
| autoRotate | boolean |
false |
3D 模型自动旋转。运行时改 prop 即时生效,也可用视图工具栏切换 |
| showGrid | boolean |
false |
3D 视图显示地面网格。运行时改 prop 即时生效 |
| showAxis | boolean |
false |
3D 视图显示坐标轴。运行时改 prop 即时生效 |
| dracoDecoderPath | string |
"" |
glTF 内嵌 DRACO 压缩时的解码器目录;默认留空即可,使用 three 自带的本地 wasm 解码器,仅在需指向自建/CDN 路径时覆盖 |
| pptxMode | "slide" | "list" |
— | PPTX 呈现方式:slide=单页翻页,list=全部页纵向连续滚动。不传时由组件内部维护(默认 list)并在工具栏提供「单页/连续」切换;传入后由宿主固定,用户无法切换 |
| pptxShowPageNav | boolean |
false |
是否在 PPTX 工具栏显示「上一页/下一页」按钮,仅 slide 模式有意义 |
| pdfMode | "iframe" | "pdfjs" |
— | PDF 呈现方式:iframe=浏览器原生,pdfjs=pdf.js 自绘。不传时由组件内部维护(默认 pdfjs);传入后由宿主固定 |
| pdfShowModeToggle | boolean |
false |
是否在 PDF 工具栏显示「原生 / 自绘」切换按钮,仅 pdfMode 未显式指定时生效 |
| videoPlayer | "native" | "xgplayer" |
"native" |
视频播放器模式:native=浏览器原生 <video>(零额外依赖);xgplayer=西瓜播放器(自带倍速/截图/画中画/设置面板,.flv/.m3u8 经官方引擎可播)。仅对 video 生效;分包(xgplayer/xgplayer-flv/xgplayer-hls)按需懒加载,native 模式不下载 |
| showClose | boolean |
false |
顶栏最右侧显示「关闭」按钮,点击触发 close 事件;开启后聚焦在组件内按 Esc 等同点击关闭(不劫持宿主页面的 Esc) |
| showThemeToggle | boolean |
true |
顶栏显示「深/浅主题切换」按钮 |
| showTopBar | boolean |
true |
是否显示顶栏(文件名 / 工具栏 / 保存 / 全屏 / 关闭),对所有查看器生效 |
| showBottomBar | boolean |
true |
是否显示底栏(帮助提示 / 媒体信息),对所有查看器生效 |
| toolsPosition | "top" | "bottom" |
"top" |
查看器工具按钮(缩放 / 翻页 / 旋转 / 测量 / 图层等)的摆放位置。"bottom" 时这批按钮改为悬浮在内容区域底部(浮于预览内容之上、居中、不占用底栏),右上角公共按钮(主题 / 保存 / 全屏 / 关闭)不受影响;无工具按钮的查看器(音视频等)不渲染悬浮工具条。工具条含下拉按钮(3D 剖切 / DXF 测量)时菜单自动改为向上弹出 |
| maxFileSize | number |
200 |
本地文件大小上限(MB),超限直接报错不进入解析;传 0 或负数表示不限制。仅对 file 生效 |
| archiveEntryMaxSize | number |
200 |
压缩包内单个条目解压后体积上限(MB),超限直接拒绝解压并提示可下载;传 0 或负数不限制。仅对 zip 生效——zip 压缩比可达上千倍,按中央目录声明的原始体积事前拦截比解压到一半内存耗尽更可控 |
| archiveShowList | boolean |
true |
压缩包预览时是否显示左侧条目列表。关闭后列表(含折叠/展开入口)整体隐藏,视口占满并自动预览主条目;嵌套压缩包的内层列表跟随同一开关。条目切换只能由宿主换源完成 |
| disableCache | boolean |
false |
是否关闭远程源内存缓存(LRU,5 条 / 256MB 预算)。开启缓存时同地址重复预览与顶栏保存直接复用、不再二次下载;内存敏感的宿主可关闭。本地 file 不受影响,PDF url 模式走 pdf.js 自己的流式请求、不经过该缓存。缓存按组件实例隔离(每个实例一份、卸载即释放),本开关只作用于当前实例 |
| requestHeaders | Record<string, string> |
— | 远程地址请求附带的自定义请求头(鉴权 Authorization、临时签名等)。所有远程读取统一携带:文档解析、PDF 预检与渲染、图片/音视频/3D/DXF 加载、顶栏保存。本地 file 不受影响。注意:带请求头的音视频与 iframe 模式 PDF 会先整包下载为 blob 再展示(无 Range 流式) |
| watermark | string | WatermarkOptions |
— | 预览区水印。传字符串等价 { text };不传或 text 为空不渲染。平铺覆盖整个预览区、点击穿透,详见「水印」一节 |
| locale | Partial<ViewerLocale> |
— | 界面文案覆盖,与内置中文浅合并(见「文案(locale)」一节);初始化后固定,切换语言请配合 :key 重建组件 |
事件
| 事件 | 载荷 | 说明 |
|---|---|---|
| loaded | { type, ... } |
解析成功;type 为命中的查看器类型,其余字段随查看器不同 |
| error | unknown(通常为 Error) |
文件加载 / 解析失败 |
| progress | number(0-100) |
加载进度,仅 3D / DXF 等有进度的查看器触发 |
| close | — | 点击顶栏「关闭」按钮,由宿主决定关闭弹窗 / 清空预览 |
宿主方法(ref expose)
通过模板 ref 可调用组件暴露的两个方法:
const previewRef = ref();
previewRef.value.reload(); // 重新加载当前源(整只查看器重建,重新拉取/解析)
previewRef.value.clearCache(); // 清空本实例的远程源内存缓存,下次访问重新拉取
reload() 在没有当前源时为空操作(不会报错)。
另外,切换 url / file 时在途的网络请求会被自动取消(AbortController),不会等旧文件下载完才切换;url 与 file 同时清空时组件回到空态拖拽提示。
主题
组件内置深 / 浅两态:默认跟随系统 prefers-color-scheme,用户点击顶栏主题按钮后以手动选择为准(可用 showThemeToggle 关闭该按钮)。根元素带 data-theme="light|dark",颜色统一走 --mv-* 设计令牌,宿主可覆盖以自定义配色。
令牌清单
在宿主样式里覆盖令牌即可定制配色(写在能作用到 .file-preview 的选择器上):
.file-preview {
--mv-accent: #7c5cff; /* 例如:把品牌色换成紫罗兰 */
}
| 令牌 | 深色默认 | 浅色 |
|---|---|---|
| --mv-surface | rgb(38 38 38 / 62%) |
rgb(10 10 10 / 3%) |
| --mv-surface-strong | rgb(38 38 38 / 82%) |
rgb(255 255 255 / 92%) |
| --mv-panel-bg | #262626 |
#ffffff |
| --mv-bar-bg | #171717 |
#f5f5f5 |
| --mv-border | rgb(250 250 250 / 10%) |
rgb(10 10 10 / 10%) |
| --mv-border-strong | rgb(250 250 250 / 30%) |
rgb(10 10 10 / 20%) |
| --mv-canvas | transparent |
#f8f8f8 |
| --mv-scene-bg | #171717 |
#f8f8f8 |
| --mv-viewer-bg | radial-gradient(120% 120% at 50% 0%, #1d1d1d, #131313) |
#f8f8f8 |
| --mv-text | #e5e5e5 |
#404040 |
| --mv-text-dim | rgb(229 229 229 / 60%) |
rgb(64 64 64 / 60%) |
| --mv-text-mute | rgb(229 229 229 / 30%) |
rgb(64 64 64 / 40%) |
| --mv-accent | #00a6f4 |
#00bcff |
| --mv-accent-strong | #0084d1 |
#00a6f4 |
| --mv-accent-soft | rgb(0 166 244 / 16%) |
rgb(0 188 255 / 12%) |
| --mv-accent-soft-strong | rgb(0 166 244 / 26%) |
rgb(0 188 255 / 18%) |
| --mv-accent-ring | rgb(0 166 244 / 50%) |
rgb(0 188 255 / 40%) |
| --mv-accent-text | #74d4ff |
#0084d1 |
| --mv-danger | #fb2c36 |
#e03131 |
| --mv-content-text | #d4d4d4 |
#404040 |
| --mv-content-heading | #e5e5e5 |
#262626 |
| --mv-code-bg | #262626 |
rgb(10 10 10 / 5%) |
| --mv-code-text | #e5e5e5 |
#404040 |
| --mv-pre-bg | #0a0a0a |
#fafafa |
| --mv-pre-border | #262626 |
rgb(10 10 10 / 10%) |
| --mv-pre-text | #d4d4d4 |
#171717 |
| --mv-th-bg | #262626 |
rgb(10 10 10 / 3%) |
| --mv-row-alt | rgb(255 255 255 / 2%) |
rgb(10 10 10 / 3%) |
| --mv-toc-bg | rgb(0 0 0 / 16%) |
rgb(10 10 10 / 3%) |
| --mv-desk-bg | #262626 |
#ececee |
| --mv-selected | rgb(255 255 255 / 10%) |
rgb(10 10 10 / 10%) |
| --mv-surface-hover | rgb(255 255 255 / 10%) |
rgb(10 10 10 / 5%) |
| --mv-tag-bg | #363636 |
#e6e6e6 |
| --mv-radius-sm | 6px |
同深色 |
| --mv-radius | 10px |
同深色 |
| --mv-radius-lg | 16px |
同深色 |
| --mv-shadow | 0 12px 40px rgb(0 0 0 / 45%) |
0 12px 40px rgb(10 10 10 / 16%) |
| --mv-blur | blur(16px) saturate(140%) |
同深色 |
| --mv-ease | cubic-bezier(0.4, 0, 0.2, 1) |
同深色 |
尺寸 / 圆角 / 阴影 / 缓动等结构令牌(
--mv-radius*、--mv-shadow、--mv-blur、--mv-ease)两套主题共用,仅颜色类令牌随主题切换。
文案(locale)
界面默认为中文,可通过 locale prop 覆盖任意条目(浅合并,未提供的键回落默认值):
<FilePreview :url="url" :locale="{ save: 'Save', close: 'Close', loadFailedTitle: 'Failed to load' }" />
可覆盖键见类型 ViewerLocale(包的类型导出):顶栏按钮(save / close / toLightTheme / toDarkTheme …)、容器状态(loading / loadFailedTitle / dropToPreview / 错误映射 errNetwork / err403 …)、面板(panelModelTree / panelLayers / hideAll / showAll / 页签 tabFloor / tabComponent 等)、Markdown 目录(toc / tocAria / tocExpand / tocCollapse / tocChildExpandPrefix / tocChildCollapsePrefix / tocChildSuffix)、表格图片预览(clickPreviewTitle / imagePreviewAria / closeEscTitle / closeImagePreviewAria / imagePreviewAlt)、PPTX 失败兜底(pptxNoSlides)。完整键位与内置中文文案见类型声明。注意 locale 初始化后固定,不响应式更新。
交互
- 空态:未提供数据源时显示拖拽提示。
- 拖拽:支持直接把文件拖入组件区域预览。
- 全屏:图片 / 音视频 / 3D 等查看器顶栏提供全屏按钮。
水印
企业预览场景(图纸 / 合同类文档)常要求在预览区叠加当前用户标识,防止截屏外传:
<!-- 字符串简写 -->
<FilePreview :url="url" watermark="预览人:张三 2026-10-06" />
<!-- 完整配置 -->
<FilePreview
:url="url"
:watermark="{
text: ['内部资料', '预览人:张三'],
opacity: 0.16,
fontSize: 15,
rotate: -22,
gapX: 180,
gapY: 140,
color: 'rgba(255, 255, 255, 0.9)'
}"
/>
水印为 canvas 绘制的平铺图层,覆盖整个预览区(含顶栏/底栏),pointer-events 穿透不影响任何交互与全屏;未配置 color 时按深/浅主题自动取前景色,主题切换自动重绘。tile 按设备像素比绘制、按逻辑像素平铺(background-size),高分屏上文字不发虚。
防篡改
水印默认开启防篡改保护:水印节点被删除、style/class 被改动时自动恢复——MutationObserver 即时校正 + 周期巡检兜底(观察器本身被脚本 disconnect 也能恢复),且关键属性(背景图/平铺尺寸/层级/点击穿透)以 !important 行内样式写入,可抵御外部样式表的 !important 覆盖。宿主需要自行操控水印 DOM 时可关闭:
<FilePreview :watermark="{ text: '内部资料', tamperProof: false }" />
查看器工具栏的全屏按钮全屏的是组件根容器而非查看器自身区域,水印与顶栏/底栏在全屏下同样覆盖——不存在「全屏后无水印可截图」的绕过口(独立使用某个查看器组件、无容器注入时回落为全屏查看器自身)。
防篡改针对的是 DevTools 手动删改与常规脚本移除,无法对抗页面内任意脚本——客户端水印本质是视觉威慑,强对抗需求请配合服务端手段(下载/导出文件烙印水印、访问审计等)。
带鉴权的远程文件
文件服务需要登录态/签名时,通过 requestHeaders 传入请求头,组件内所有远程读取统一携带(各查看器也可单独使用时各自传入):
<FilePreview :url="fileUrl" :request-headers="{ Authorization: `Bearer ${token}` }" />
实现方式按载体自动区分:文档解析(docx/xlsx/pptx/md/文本)、pdf.js 渲染(httpHeaders,支持 Range 分片)、3D 模型(three loader 原生携带)直接随请求发送;无法携带请求头的载体(<img>、<video>/<audio>、iframe 模式 PDF、dxf-viewer)自动先拉取为 blob 中转。注意:
- blob 中转意味着整包下载,大视频/大 PDF(iframe 模式)没有流式范围请求;
- 3D 多文件格式(
.gltf+ 外部贴图、.obj+.mtl)中主文件携带请求头,由 three 内部加载器发起的贴图等子资源不保证携带——此类场景建议.glb内嵌资源或经代理直连; - 顶栏「保存」同样携带请求头。带请求头的地址若 fetch 失败(鉴权过期、断网),保存会判定为失败并在顶栏给出提示,而不是静默降级为必然失败的直链;未带请求头时跨域 fetch 失败仍会降级为直链下载。预览与保存共用内存缓存,保存不触发二次整包下载。
导出
除默认导出的 FilePreview 组件外,还导出:
- 工具函数:
detectViewerType、getFileExtension、getFileName、normalizeExtension、formatDuration,以及类型判断isImage/isText/isCsv/isMarkdown/isPdf/isOffice/isAudio/isVideo/isThree/isSupportedExtension。 - 扩展名常量:
IMAGE_EXTENSIONS、TEXT_EXTENSIONS、MARKDOWN_EXTENSIONS、PDF_EXTENSIONS、OFFICE_EXTENSIONS、LEGACY_OFFICE_EXTENSIONS、CSV_EXTENSIONS、AUDIO_EXTENSIONS、VIDEO_EXTENSIONS、THREE_EXTENSIONS、ARCHIVE_EXTENSIONS、SUPPORTED_EXTENSIONS,以及可直接用于<input type="file" :accept="ACCEPT_ATTR">的ACCEPT_ATTR。 - 文案:
zhCN(内置中文文案全量对象,可作为自定义 locale 的基底)、mergeLocale(Partial<ViewerLocale>与内置值的浅合并函数)。 - 类型声明:
ModelViewerProps、ModelViewerEmits、ViewerType、FileSource、ViewerLoadedResult、ViewerProps、ViewerEmits、ProgressViewerEmits、ViewerTheme、ViewerLocale、ThreeViewerProps、PdfMode、PdfViewerProps、PptxMode、PptxViewerProps、UnsupportedViewerProps、ModelInfo、DxfLayer、MediaInfo、WatermarkOptions。
注意事项
PDF 大文件
pdf.js 模式按页虚拟渲染:只有视口附近(前后各 2 页)的页面实际渲染成 canvas,其余页以同高占位槽撑出滚动条,几百上千页的文档不会把内存打爆;页码跟踪、缩放锚点均基于占位槽定位。
Excel 解析器
xlsx 由 exceljs 解析(值、公式缓存结果、合并区、单元格样式、行高列宽、WPS 内嵌图片 ID);数值与日期按 Excel 数字格式(numFmt)渲染。整表超过 5000 行 / 200 列会截断并在底栏提示。旧版二进制 .xls(BIFF 格式)无法解析,见「支持格式」一节的回退说明。
大表走虚拟滚动:只渲染视口附近的行(视口前后留 buffer),上下用同高占位行撑出滚动条。
表格图片预览
xlsx 里的图片统一按「锚点单元格内绝对定位」渲染,支持两类来源:WPS 单元格函数图(DISPIMG)与 drawing.xml 浮动图。
- 定位:以图片所在
td为坐标系,位置由表格布局本身决定,不受视口尺寸、滚动位置、是否全屏影响;尺寸取文件里记录的行高/列宽(或ext原始像素),与 Excel / WPS 保存的值一致。 - 放大:点击单元格图片打开灯箱浮层,原图按
object-fit: contain铺满视口;点击空白处或右上角关闭按钮关闭。 - 与全屏叠加:全屏状态下浮层自动 teleport 到全屏元素内部(浏览器只会渲染全屏子树,挂在
body上的浮层会被整块盖住、表现为「点了没反应」);退出全屏后自动搬回body。 - Esc 分层退出:全屏 + 浮层同时存在时,第一次
Esc只退出全屏、图片保留,再按一次才关闭图片;未全屏时Esc直接关闭。ESC 处理挂在 document 捕获阶段,不会冒泡到外层导致整个预览被关掉。
PPTX 解析失败
第三方生成器(如 pptxgenjs)产出的结构不完整文件,pptx-preview 可能静默吞掉解析异常并表现为「成功解析出 0 页」。此时查看器按 locale.pptxNoSlides 给出明确提示(建议用 PowerPoint 重新导出),而不是留一个空白画面。
该兜底在 slide(单页翻页)与 list(连续滚动)两种模式下均生效——slide 模式下库会尝试渲染不存在的首页导致 TypeError,查看器捕获后统一转为友好报错,不会把原始技术错误泄漏给用户,也不会因 ResizeObserver 触发重建循环而刷屏。
安全
Office 文档(docx / pptx)由 docx-preview / pptx-preview 把文档 XML 直接转成 HTML 插入页面;上传方可控的恶意 XML 可能携带脚本、事件属性或 javascript: 链接,构成存储型 XSS 面。库在渲染完成后对产物 DOM 执行一次 DOMPurify 就地消毒(IN_PLACE 模式,保留元素实例与 data:/blob: 图片 URI),Markdown 同样经 DOMPurify 处理。xlsx 走 Vue 文本插值(自动转义)且图片为 blob: src,构造上安全,不额外消毒。
压缩文件预览
zip 压缩包由 jszip 解析,预览时左侧显示条目列表(文件名、扩展名标签、体积),点击条目即在右侧内联预览——条目按扩展名自动分发到与直接预览同一文件完全相同的查看器(3D / PDF / Office / 图片 / 音视频等),内嵌查看器的工具栏经 Teleport 托管到外层顶栏,视觉与独立预览一致。
- 条目管理:列表支持按包内路径前缀过滤(大小写不敏感)、循环切换排序(默认 → 名称 → 大小 → 类型);条目按目录分组显示。列表可收起让预览视口占满,收起后展开入口位于压缩包顶栏工具栏(不与预览区左上角冲突——那里是内层查看器的面板位:Markdown 目录、3D 模型树、DXF 图层面板都会占);仅当宿主隐藏了顶栏(
showTopBar=false)时才回落到预览区左上角的悬浮按钮。宿主通过archiveShowList=false关闭列表时不给任何展开入口。 - 单条目下载:每个条目右侧带下载按钮,带实时进度百分比;单个条目下载失败时内联红字提示,不影响其余条目预览。
- 嵌套压缩包:zip 内嵌 zip 时自动递归预览,内层压缩包保持自带顶栏(显示内层包名),列表跟随外层
archiveShowList开关。 - 体积防线:
archiveEntryMaxSize(默认 200MB)按中央目录声明的原始体积事前拦截超大条目,超限直接拒绝解压并提示可下载,而非解压到一半内存耗尽才崩溃。条目解析失败只在该条目的预览区给出内联提示,列表保持可用可换条目。 - 保存:顶栏「保存」下载的是压缩包本身(当前层),而非当前预览的条目。
UnsupportedViewer 连续切换
连续切换多个不支持的文件(如 .doc → .xls → .ppt → .xyz)时,Vue 会复用同一个 UnsupportedViewer 实例(组件类型相同且 key 未变),onMounted 不会再次触发。查看器内部 watch 了 source 变化,每次切源都会重新上报 loaded 事件,确保宿主的 loading 遮罩不会永久停留。
Draco 压缩模型
预览 draco 压缩的 glb/gltf 无需额外配置:three 的 DRACOLoader 默认使用自带的本地 wasm 解码器,打包器会自动产出对应静态资源。仅当需要指向自建 / CDN 上的 three 官方解码器 目录时,才通过 draco-decoder-path 传入(该目录需含 draco_wasm_wrapper.js 与 draco_decoder.wasm)。
Related Packages
Version History
| Version | Released | License |
|---|---|---|
| 1.6.1 | MIT | |
| 1.6.0 | MIT | |
| 1.5.1 | MIT | |
| 1.5.0 | MIT | |
| 1.4.0 | MIT | |
| 1.3.2 | MIT | |
| 1.3.1 | MIT | |
| 1.3.0 | MIT | |
| 1.2.0 | MIT | |
| 1.1.0 | MIT | |
| 1.0.8 | MIT | |
| 1.0.7 | MIT | |
| 1.0.5 | MIT | |
| 1.0.4 | MIT | |
| 1.0.3 | MIT | |
| 1.0.2 | MIT | |
| 1.0.1 | MIT | |
| 1.0.0 | MIT | |
| 0.2.8 | MIT | |
| 0.2.7 | MIT |
Pre-releases (1)
| Version | Released | License |
|---|---|---|
| 0.0.0-stage |