API Documentation

Open File Viewer 接入与 API 指南

开始接入 在线体验

Overview

从一个稳定容器开始接入文件预览

Open File Viewer 由一个框架无关的 core 加多个 UI 适配器组成。核心负责文件识别、插件匹配、容器尺寸、工具栏命令、错误降级和生命周期;React、Vue、Svelte 适配器只是把同一套能力包装成组件。

4Vanilla JS / React / Vue / Svelte
15+内置预览插件
1统一插件协议

Frameworks

支持的框架

Vanilla JavaScript

直接调用 createViewer()。适合任意 Web 页面、低代码平台、微前端容器和非框架项目。

React

使用 @open-file-viewer/reactFileViewer 组件,支持 renderToolbar 完全替换工具栏。

Vue

使用 @open-file-viewer/vueOpenFileViewer 组件,支持 #toolbar slot。

Svelte

使用 @open-file-viewer/svelteOpenFileViewer 组件,支持 slot="toolbar"renderToolbar

Install

安装

core 是必装包;如果使用具体框架,再安装对应适配器。

terminal
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

viewer.ts
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

AttachmentPreview.tsx
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

AttachmentPreview.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

AttachmentPreview.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)

containerHTMLElement | string必填。预览器挂载容器,传字符串时会通过 document.querySelector 查找。
fileFile | Blob | string | ArrayBuffer单文件预览源。URL 需要目标资源允许跨域访问。
files(PreviewSource | PreviewItem)[]多文件队列。配合默认工具栏可以上一份、下一份切换。
initialIndexnumber多文件队列初始下标,默认从第一个文件开始。
fileNamestring当文件源不是 File 时建议传入,插件会根据扩展名判断格式。
mimeTypestring补充 MIME 类型,适合 Blob、ArrayBuffer 或扩展名不可靠的远程地址。
width / heightnumber | string预览容器尺寸。常用 100%640px70vh
fitcontain | cover | width | height | actual | scale-down内容适配方式。不同插件会尽量遵循同一语义。
pluginsPreviewPlugin[]插件列表。按数组顺序匹配,建议把更具体的业务插件放在通用插件前面。
fallbackinline | download | custom不支持格式的降级策略。需要完全自定义时配合 renderFallback
toolbarboolean | PreviewToolbarOptions默认工具栏开关或配置对象,可控制按钮、文案、图标、顺序和业务动作。
themelight | dark | auto预览器主题。auto 会跟随系统或宿主环境。
classNamestring添加到根节点的业务 class,便于局部样式覆盖。
onLoad(file) => void当前文件加载成功后触发。
onError(error, file?) => void插件渲染或文件读取失败时触发。
onUnsupported(file) => void没有插件匹配当前文件时触发。

Viewer Instance

实例方法

reload(file?)Promise<void>重新加载当前文件,或传入新文件源进行替换。
next()Promise<void>切换到队列中的下一个文件。
previous()Promise<void>切换到队列中的上一个文件。
goTo(index)Promise<void>切换到指定下标。
getCurrentIndex()number返回当前队列下标。
resize()void容器尺寸变化后主动通知当前插件重新计算布局。
destroy()void销毁预览器、清理事件和插件资源。

Toolbar

工具栏自定义

工具栏可以从轻到重分三层定制:配置内置按钮、增加业务按钮、完全替换渲染。样式层也可以覆盖 .ofv-toolbar.ofv-toolbar button.ofv-toolbar-search

toolbar.ts
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
});
自定义文案

通过 labelstitles 把 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 会按插件数组顺序查找第一个匹配项,并把统一的上下文交给它渲染。

custom-plugin.ts
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

内置插件清单

imagePlugin

jpg、png、gif、webp、avif、svg、bmp、ico、heic、heif 等图片格式。

pdfPlugin

PDF 渲染、缩放、搜索、打印和高清画布渲染。

officePlugin

docx、xlsx、pptx、rtf、odt、ods、odp 等现代 Office 与开放文档格式。

textPlugin

txt、md、json、yaml、toml、代码文件和语法高亮。

archivePlugin

zip、rar、7z、tar、gz 等压缩包目录和文件结构。

gisPlugin

geojson、kml、kmz、gpx、topojson、shp 等地图数据。

model3dPlugin

gltf、glb、obj、stl、fbx、dae、3mf、usdz 等 3D 模型。

cadPlugin

dxf、dwg、step、ifc、gds、oas 等工程图纸与芯片版图预览。

emailPlugin

eml、msg、mbox 邮件正文、头部信息和附件结构。

FAQ

常见问题

远程 URL 预览为什么失败?

浏览器必须能直接访问文件,并且目标地址需要允许 CORS。对于私有文件,建议由业务后端签发临时 URL,或先 fetch 成 Blob 再传给预览器。

容器宽度变化后如何避免排版问题?

优先给外层容器稳定的 width / height,并在布局变化后调用实例的 resize()。内置插件会尽量把滚动限制在预览容器内部。

如何接入服务端转换?

可以写一个自定义插件,在 render(ctx) 中调用你的转换服务,然后把返回的 HTML、图片、PDF 或结构化数据渲染到 ctx.viewport