直接调用 createViewer()。适合任意 Web 页面、低代码平台、微前端容器和非框架项目。
API Documentation
Open File Viewer 接入与 API 指南
Overview
从一个稳定容器开始接入文件预览
Open File Viewer 由一个框架无关的 core 加多个 UI 适配器组成。核心负责文件识别、插件匹配、容器尺寸、工具栏命令、错误降级和生命周期;React、Vue、Svelte 适配器只是把同一套能力包装成组件。
Frameworks
支持的框架
使用 @open-file-viewer/react 的 FileViewer 组件,支持 renderToolbar 完全替换工具栏。
使用 @open-file-viewer/vue 的 OpenFileViewer 组件,支持 #toolbar slot。
使用 @open-file-viewer/svelte 的 OpenFileViewer 组件,支持 slot="toolbar" 和 renderToolbar。
Install
安装
core 是必装包;如果使用具体框架,再安装对应适配器。
npm install @open-file-viewer/core
npm install @open-file-viewer/react
npm install @open-file-viewer/vue
npm install @open-file-viewer/svelte
默认 UI、工具栏、错误态、各类插件容器都依赖 @open-file-viewer/core/style.css。业务项目可在它之后覆盖 CSS 变量或 class。
Quick Start
如何接入
Vanilla JS
import {
createViewer,
imagePlugin,
officePlugin,
pdfPlugin,
textPlugin
} from "@open-file-viewer/core";
import "@open-file-viewer/core/style.css";
import workerSrc from "pdfjs-dist/build/pdf.worker.mjs?url";
const viewer = createViewer({
container: "#viewer",
file,
fileName: file.name,
height: "70vh",
theme: "auto",
toolbar: true,
plugins: [
imagePlugin(),
pdfPlugin({ workerSrc }),
officePlugin(),
textPlugin()
]
});
React
import { FileViewer } from "@open-file-viewer/react";
import { imagePlugin, officePlugin, pdfPlugin, textPlugin } from "@open-file-viewer/core";
import "@open-file-viewer/core/style.css";
const plugins = [imagePlugin(), pdfPlugin({ workerSrc }), officePlugin(), textPlugin()];
export function AttachmentPreview({ file }: { file: File }) {
return (
<FileViewer
file={file}
fileName={file.name}
height="640px"
toolbar
plugins={plugins}
/>
);
}
Vue
<script setup lang="ts">
import { OpenFileViewer } from "@open-file-viewer/vue";
import { imagePlugin, officePlugin, pdfPlugin, textPlugin } from "@open-file-viewer/core";
import "@open-file-viewer/core/style.css";
defineProps<{ file: File }>();
const plugins = [imagePlugin(), pdfPlugin({ workerSrc }), officePlugin(), textPlugin()];
</script>
<template>
<OpenFileViewer
:file="file"
:file-name="file.name"
height="640px"
toolbar
:plugins="plugins"
/>
</template>
Svelte
<script lang="ts">
import { OpenFileViewer } from "@open-file-viewer/svelte";
import { imagePlugin, officePlugin, pdfPlugin, textPlugin } from "@open-file-viewer/core";
import "@open-file-viewer/core/style.css";
export let file: File;
const plugins = [imagePlugin(), pdfPlugin({ workerSrc }), officePlugin(), textPlugin()];
</script>
<OpenFileViewer {file} fileName={file.name} height="640px" toolbar {plugins} />
Core API
createViewer(options)
HTMLElement | string必填。预览器挂载容器,传字符串时会通过 document.querySelector 查找。File | Blob | string | ArrayBuffer单文件预览源。URL 需要目标资源允许跨域访问。(PreviewSource | PreviewItem)[]多文件队列。配合默认工具栏可以上一份、下一份切换。number多文件队列初始下标,默认从第一个文件开始。string当文件源不是 File 时建议传入,插件会根据扩展名判断格式。string补充 MIME 类型,适合 Blob、ArrayBuffer 或扩展名不可靠的远程地址。number | string预览容器尺寸。常用 100%、640px、70vh。contain | cover | width | height | actual | scale-down内容适配方式。不同插件会尽量遵循同一语义。PreviewPlugin[]插件列表。按数组顺序匹配,建议把更具体的业务插件放在通用插件前面。inline | download | custom不支持格式的降级策略。需要完全自定义时配合 renderFallback。boolean | PreviewToolbarOptions默认工具栏开关或配置对象,可控制按钮、文案、图标、顺序和业务动作。light | dark | auto预览器主题。auto 会跟随系统或宿主环境。string添加到根节点的业务 class,便于局部样式覆盖。(file) => void当前文件加载成功后触发。(error, file?) => void插件渲染或文件读取失败时触发。(file) => void没有插件匹配当前文件时触发。Viewer Instance
实例方法
Promise<void>重新加载当前文件,或传入新文件源进行替换。Promise<void>切换到队列中的下一个文件。Promise<void>切换到队列中的上一个文件。Promise<void>切换到指定下标。number返回当前队列下标。void容器尺寸变化后主动通知当前插件重新计算布局。void销毁预览器、清理事件和插件资源。Toolbar
工具栏自定义
工具栏可以从轻到重分三层定制:配置内置按钮、增加业务按钮、完全替换渲染。样式层也可以覆盖 .ofv-toolbar、.ofv-toolbar button、.ofv-toolbar-search。
createViewer({
container: "#viewer",
file,
toolbar: {
labels: {
download: "下载",
fullscreen: "全屏",
search: "搜索"
},
order: ["search", "download", "favorite", "approve", "share", "fullscreen"],
actions: [
{ id: "favorite", label: "收藏", onClick: (ctx) => favoriteFile(ctx.file) },
{ id: "approve", label: "审批", onClick: (ctx) => openApproval(ctx.file) },
{ id: "share", label: "分享", onClick: (ctx) => shareFile(ctx.file) }
]
},
plugins
});
通过 labels 和 titles 把 Download、Search 等按钮改成中文或业务词。
order 同时支持内置按钮 ID 和业务按钮 ID。
icons 接收 SVG 字符串、HTMLElement 或 SVGElement。
actions 可增加审批、收藏、分享等按钮,并支持 hidden / disabled 函数。
React / Vue / Svelte 完全替换工具栏
React render prop
<FileViewer
file={file}
toolbar
renderToolbar={(ctx) => (
<div className="business-toolbar">
<button onClick={ctx.previous} disabled={!ctx.canPrevious}>上一份</button>
<span>{ctx.index + 1} / {ctx.length}</span>
<button onClick={ctx.download}>下载</button>
<button onClick={() => approve(ctx.file)}>审批</button>
</div>
)}
/>
Vue slot
<OpenFileViewer :file="file" toolbar>
<template #toolbar="ctx">
<div class="business-toolbar">
<button @click="ctx.previous()" :disabled="!ctx.canPrevious">上一份</button>
<span>{{ ctx.index + 1 }} / {{ ctx.length }}</span>
<button @click="ctx.download()">下载</button>
<button @click="approve(ctx.file)">审批</button>
</div>
</template>
</OpenFileViewer>
Svelte slot
<OpenFileViewer {file} toolbar>
<svelte:fragment slot="toolbar" let:ctx>
<div class="business-toolbar">
<button on:click={ctx.previous} disabled={!ctx.canPrevious}>上一份</button>
<span>{ctx.index + 1} / {ctx.length}</span>
<button on:click={ctx.download}>下载</button>
<button on:click={() => approve(ctx.file)}>审批</button>
</div>
</svelte:fragment>
</OpenFileViewer>
Plugin Protocol
插件机制
插件只需要实现 match(file) 和 render(ctx)。当文件进入预览器时,core 会按插件数组顺序查找第一个匹配项,并把统一的上下文交给它渲染。
import type { PreviewPlugin } from "@open-file-viewer/core";
export function customReportPlugin(): PreviewPlugin {
return {
name: "custom-report",
match(file) {
return file.extension === "report" || file.mimeType === "application/x-report";
},
render(ctx) {
const element = document.createElement("div");
element.className = "report-preview";
element.textContent = ctx.file.name;
ctx.viewport.append(element);
return {
resize(size) {
element.style.setProperty("--viewer-width", `${size.width}px`);
},
command(command) {
if (command === "zoom-in") {
element.classList.add("zoomed");
return true;
}
return false;
},
destroy() {
element.remove();
}
};
}
};
}
如果你有业务专属格式或服务端转换结果,建议把自定义插件放在通用插件之前,避免被 textPlugin 或 fallback 先匹配。
Built-in Plugins
内置插件清单
jpg、png、gif、webp、avif、svg、bmp、ico、heic、heif 等图片格式。
PDF 渲染、缩放、搜索、打印和高清画布渲染。
docx、xlsx、pptx、rtf、odt、ods、odp 等现代 Office 与开放文档格式。
txt、md、json、yaml、toml、代码文件和语法高亮。
zip、rar、7z、tar、gz 等压缩包目录和文件结构。
geojson、kml、kmz、gpx、topojson、shp 等地图数据。
gltf、glb、obj、stl、fbx、dae、3mf、usdz 等 3D 模型。
dxf、dwg、step、ifc、gds、oas 等工程图纸与芯片版图预览。
eml、msg、mbox 邮件正文、头部信息和附件结构。
FAQ
常见问题
远程 URL 预览为什么失败?
浏览器必须能直接访问文件,并且目标地址需要允许 CORS。对于私有文件,建议由业务后端签发临时 URL,或先 fetch 成 Blob 再传给预览器。
容器宽度变化后如何避免排版问题?
优先给外层容器稳定的 width / height,并在布局变化后调用实例的 resize()。内置插件会尽量把滚动限制在预览容器内部。
如何接入服务端转换?
可以写一个自定义插件,在 render(ctx) 中调用你的转换服务,然后把返回的 HTML、图片、PDF 或结构化数据渲染到 ctx.viewport。