云计算百科
云计算领域专业知识百科平台

文件预览服务:kkFileView、File Viewer

概述

在企业级应用开发场景下,非常常见的一个需求就是多格式文档的预览,包括但不限于:TXT、CSV、PDF、Word、PPT、Excel等。通常情况下,这些文件会上传到MinIO、阿里云OSS或腾讯云COS。

根据个人知识所限,MinIO只能预览TXT、CSV、PDF,并不能预览Office三件套,更别谈其他各种各样的文件格式。

那商业化文件存储平台呢?

OSS

亲自尝试,阿里云OSS预览Word文档,需绑定IMM智能媒体项目 在这里插入图片描述 点击【绑定】 在这里插入图片描述 点击【授权】 在这里插入图片描述 可惜,OSS免费开通,IMM需付费使用;本着写技术博客的严谨精神,还是开通体验一下 在这里插入图片描述 点击桶(Bucket)内的.docx文件,自动下载线性代数.htm文件,浏览器打开此文件,加载几分钟还出来。 在这里插入图片描述 商业平台能力,就这样????

另外,再说一个很搞笑的Bug(非常明显的问题): 在这里插入图片描述 Bucket列表为空,创建一个preview-test的桶,结果提示我已存在,我他妈为啥要关心这个名称被其他用户占用???OSS作为SaaS应用,而SaaS最基本的概念就是多租户,不同用户创建相同的Bucket名称,有什么问题吗?

上面说到有2个方案,方案1是图片方案,猜测是基于截图来实现,限于时间因素,未经验证。有空补上。

关于IMM的介绍:可绑定智能媒体管理产品,来做数据分析预处理

  • 调用方式:OSS域名/sample_object?x-oss-process=imm/action,param_value
  • 接口实例:OSS域名/family.jpg?x-oss-process=imm/detectface

IMM基于x-oss-process推出全新的文档处理、音视频处理等能力,支持样式、异步任务、批处理、触发器等多种使用方式。

COS

上传文件后,有【预览】入口 在这里插入图片描述 点击预览,果不其然,也是收费服务 在这里插入图片描述 点击【开启服务】 在这里插入图片描述 预览效果 在这里插入图片描述

开源

商业化平台能力是ok的,但涉及到企业内部安全隐私,数据泄密等问题,最好还是使用本地化部署方案。本文收集几个基于浏览器的文件预览开源项目。

kkFileView

官网,一个基于Java+Spring Boot的万能文件预览开源(GitHub,14.4K Star,3.3K Fork)项目,允许用户在浏览器端实时查看文件内容。

支持的文件类型:

  • 支持doc、docx、xls、xlsx、xlsm、ppt、pptx、csv、tsv、dotm、xlt、xltm、dot、dotx、xlam、xla等Office办公文档;
  • 支持wps、dps、et、ett、wpt等国产WPS Office办公文档;
  • 支持odt、ods、ots、odp、otp、six、ott、fodt、fods等Open Office、Libre Office办公文档;
  • 支持vsd、vsdx等Visio流程图文件;
  • 支持wmf、emf等Windows系统图像文件;
  • 支持psd等Photoshop软件模型文件;
  • 支持pdf、ofd、rtf等文档;
  • 支持xmind软件模型文件;
  • 支持bpmn工作流文件;
  • 支持eml邮件文件;
  • 支持epub图书文档;
  • 支持obj、3ds、stl、ply、gltf、glb、off、3dm、fbx、dae、wrl、3mf、ifc、brep、step、iges、fcstd、bim等3D模型文件;
  • 支持dwg、dxf等CAD模型文件;
  • 支持txt、xml(渲染),md(渲染),java、php、py、js、css等所有纯文本;
  • 支持zip、rar、jar、tar、gzip、7z等压缩包;
  • 支持jpg、jpeg、png、gif、bmp、ico、jfif、webp等图片预览(翻转,缩放,镜像);
  • 支持tif、tiff图信息模型文件;
  • 支持tga图像格式文件;
  • 支持svg矢量图像格式文件;
  • 支持mp3、wav、mp4、flv等音视频格式文件;
  • 支持avi、mov、rm、webm、ts、rm、mkv、mpeg、ogg、mpg、rmvb、wmv、3gp、ts、swf等视频格式转码预览;
  • 极易上手,使用HTTP接口访问,不需要和应用集成,具有跨系统跨语言使用的特性。提供Windows/Linux版本发行包、自定义配置文件、和一键启动/停止脚本等,极大方便部署使用,官方提供Docker镜像。

    因此仅需单独将kkFileView部署好后,文件交由minio存储和维护,然后提供文件的url地址既可实现在线预览,如下图所示:

    部署

    git clone https://github.com/kekingcn/kkFileView.git
    cd kkfileviewer
    docker build -t kkfileview:v5.0.0 .
    docker run -d -p 8012:8012 –name kkfileview kkfileview:v5.0.0

    打开:http://localhost:8012,开始体验。

    集成MinIO

    添加依赖:implementation 'io.minio:minio:8.5.17'

    application.yaml配置:

    minio:
    endpoint: http://xxxxx:9000
    accessKey: xxxx
    secretKey: xxxxx
    bucketName: test

    MinIO配置类:

    @Configuration
    public class MinioConfig {
    @Value("${minio.endpoint}")
    private String endPoint;
    @Value("${minio.accessKey}")
    private String accessKey;
    @Value("${minio.secretKey}")
    private String secretKey;
    @Value("${minio.bucketName}")
    private String bucketName;

    @Bean
    protected MinioClient minioClient(){
    return MinioClient.builder()
    .endpoint(endPoint)
    .credentials(accessKey, secretKey)
    .build();
    }
    }

    工具类:

    @Component
    public class MinioUtils {
    @Value("${minio.bucketName}")
    private String bucketName;
    @Resource
    private MinioClient minioClient;

    public ApiResult uploadFile(MultipartFile file) throws AppException {
    String fileName = System.currentTimeMillis() + file.getOriginalFilename();
    try (InputStream fi = file.getInputStream()) {
    PutObjectArgs putObjectArgs = PutObjectArgs.builder().bucket(bucketName).contentType(file.getContentType()).object(fileName).stream(fi, fi.available(), 1).build();
    minioClient.putObject(putObjectArgs);
    } catch (Exception e) {
    throw new AppException("文件上传失败" + e.getMessage());
    }
    return ApiResult.ok(fileName);
    }

    public ApiResult getPreviewUrl(String objectName) throws AppException {
    try {
    GetPresignedObjectUrlArgs urlArgs = GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(objectName).method(Method.GET).build();
    return ApiResult.ok(minioClient.getPresignedObjectUrl(urlArgs));
    } catch (Exception e) {
    throw new AppException("获取预览链接失败" + e.getMessage());
    }
    }
    }

    controller接口类:

    @RestController
    @RequestMapping("/file")
    public class FileOperationController {
    @Resource
    private MinioUtils minioUtils;

    @PostMapping("/upload")
    public ApiResult upload(MultipartFile file) throws AppException {
    return minioUtils.uploadFile(file);
    }

    @GetMapping("/getPreviewUrl")
    public ApiResult getPreviewUrl(String fileName) throws AppException {
    return minioUtils.getPreviewUrl(fileName);
    }
    }

    File Viewer

    官网,全能、纯前端、开源(GitHub,1.8K Star,185 Fork)商用友好的文件预览器。基于浏览器运行,覆盖Office、PDF、OFD、Typst、CAD、3D、压缩包、邮件、绘图、电子书、Markdown、代码、图片、音频、视频等常见业务附件。官方文档,在线Demo。

    功能价值
    全能纯前端文件预览器 文件在浏览器端完成解析和展示,业务系统可用一套组件覆盖绝大多数附件预览需求
    完全开源,Apache-2.0 协议商用友好,适合企业内部系统、SaaS产品、低代码平台和二开集成
    覆盖几乎所有常见附件场景 合同、档案、工单、知识库、工程图纸、邮箱附件、代码审阅、培训资料、压缩包归档都能进入统一预览体验
    优质且高效的代码链路 按文件类型异步加载重型依赖,PDF.js、CAD WASM、docx-preview、epub.js、libarchive等只在需要时进入页面
    可扩展性完整清晰 @file-viewer/core负责底层预览能力,Vue、React、纯Web、jQuery、Svelte等组件入口保持统一参数、事件和操作语义

    适用场景

    场景推荐能力组合
    合同审阅 Word/PDF/OFD+水印+打印+下载前置校验+文档比对
    档案归档 PDF/OFD/Office+生命周期回调+搜索定位+HTML导出
    邮箱附件归档 EML/MSG/MBOX+附件继续预览+原文下载
    工程图纸 DWG/DXF/DWF/DWFx/XPS+CAD WASM私有化+图层/结构面板
    知识库 Markdown/代码/PDF/Word+全文搜索+文本切片+来源定位
    低代码平台 Pure Web/Vue/React组件+统一options+动态文件源
    SaaS中后台 主题固定为light+权限前置操作+统一工具栏
    内网部署 静态资源自托管+Docker/静态目录+Worker/WASM路径配置

    核心架构

    架构设计对开发者的价值
    @file-viewer/core作为纯TypeScript底座 格式矩阵、渲染协议、生命周期、搜索、缩放、打印、导出、水印等能力集中沉淀,框架层更轻
    多生态标准组件拆分 Vue、React、纯Web、jQuery、Svelte等入口都只依赖core,参数和事件语义保持一致
    渲染链路按需异步加载 命中文件类型后才加载PDF.js、CAD WASM、docx-preview、epubjs、libarchive等重型依赖
    Demo、文档、Release、静态部署体系完整 官网、文档站、在线Demo、文档比对页、Docker/静态产物、npm包和Release下载物形成完整分发闭环

    开发者可从最小组件开始接入,再逐步打开水印、搜索、打印、权限前置校验、WASM私有化、文档比对和AI溯源等能力。

    扩展名支持参考packages/core/src/formats.ts,并由pnpm verify:format-support校验:194个扩展名映射,23条预览链路。不包含内部错误兜底处理器。

    类别扩展名示例渲染链路适合场景与边界
    Word/模板 docx、docm、dotx、dotm、doc、dot docx-preview、msdoc-viewer 合同、制度、报告、历史Word附件。复杂版式优先保持页面阅读效果
    Excel/表格 xlsx、xlsm、xlsb、xls、csv、ods、fods、numbers styled-exceljs+虚拟表格 业务台账、导出报表、多sheet文件。表格链路以交互查看为主
    PowerPoint pptx、pptm、potx、ppsx @aiden0z/pptx-renderer 课件、方案、汇报材料。浏览器近似渲染,复杂动画建议转PDF留档
    PDF pdf PDF.js 合同、归档件、说明书。支持页导航、目录、缩放、搜索、打印和HTML导出
    OFD ofd DLTech21/ofd.js 发票、政企归档。按需加载OFD解析链路
    Typst typ、typst Typst WASM+SVG 直接预览Typst源文件,适合技术文档和排版稿
    CAD/图纸 dwg、dxf、dwf、dwfx、xps @flyfish-dev/cad-viewer+WASM/Worker 工程图纸、设备图、DWF/DWFx/XPS审阅。私有部署需配置WASM/Worker路径
    3D模型 glb、gltf、obj、stl、ply、fbx、dae、3mf、usd等 Three.js 产品模型、工程资产、简单三维附件。复杂CAD/BIM可先转换
    压缩包 zip、7z、rar、tar、gz、xz、iso、jar、apk、cbz等 libarchive.js Worker+兼容降级 查看压缩包目录,按需解压内部文档并继续预览
    邮件 eml、msg、mbox postal-mime、msgreader 邮件归档、客服工单、附件审阅。正文隔离渲染,附件可继续预览
    绘图 excalidraw、drawio、dio 官方Excalidraw/diagrams.net链路 流程图、草图、架构图,只读预览
    电子书 epub、umd epubjs、UMD parser 内部手册、电子书、历史移动阅读文件
    Markdown/代码 md、json、js、ts、tsx、vue、py、java、sql、log等 Markdown+highlight.js 知识库、配置、源码、日志,安全地按源码展示
    图片/设计资产 png、jpg、svg、webp、heic、psd、ai、eps 浏览器图片、按需解析器 品牌素材、截图、设计附件。AI/EPS做安全摘要或PDF-backed预览
    音视频 mp3、ogg、flac、midi、mp4、webm、m3u8 原生媒体、hls.js、MIDIparser 通话录音、培训视频、媒体附件
    数据资产 sqlite、parquet、avro、wasm、webarchive、字体文件 sql.js、hyparquet、avsc、FontFace 快速查看结构、表、schema、导入导出信息

    组件生态围绕core提供多条生产可用入口。新项目推荐优先使用标准包名,历史包名继续保持兼容。

    技术栈

    技术栈推荐包名兼容包名适合场景
    Core @file-viewer/core 自研组件、底层能力、格式识别、生命周期和操作API
    Vue 3 @file-viewer/vue3 @flyfish-group/file-viewer3、file-viewer3 Vue3中后台、知识库、合同系统
    Vue 2.7 @file-viewer/vue2.7 @flyfish-group/file-viewer 存量Vue2.7项目
    Vue 2.6 @file-viewer/vue2.6 老Vue2.6项目
    React 18/19 @file-viewer/react @flyfish-group/file-viewer-react React中后台、SaaS、设计系统
    React 16.8/17 @file-viewer/react-legacy 老React项目
    纯Web/JS @file-viewer/web @flyfish-group/file-viewer-web 原生页面、Web Components外壳、微前端、script标签
    jQuery @file-viewer/jquery 老后台、CMS、传统页面
    Svelte @file-viewer/svelte Svelte应用和组件库

    对于独立静态预览站,可把自托管Demo页面放入业务iframe做隔离展示。新业务集成建议优先使用上面的原生组件或mountViewer,调试体验和事件回调会更直接。

    实战

    安装:

    pnpm add @file-viewer/vue3
    # React、纯Web、jQuery、Svelte分别安装对应包
    pnpm add @file-viewer/react
    pnpm add @file-viewer/web
    pnpm add @file-viewer/jquery
    pnpm add @file-viewer/svelte

    Vue3示例:

    <script setup lang="ts">
    import FileViewer from '@file-viewer/vue3'
    </script>
    <template>
    <div style="height: 100vh">
    <FileViewer url="/files/demo.pdf" />
    </div>
    </template>

    Vue组件会自动带上样式,父容器需要明确高度,这是所有预览器最容易被忽略的基础条件。

    React示例:

    import FileViewer from '@file-viewer/react'

    export function Preview() {
    return (
    <div style={{ height: '100vh' }}>
    <FileViewer url="/files/contract.docx" />
    </div>
    )
    }

    纯JS/Script标签:

    import { mountViewer } from '@file-viewer/web'

    const controller = mountViewer(document.getElementById('viewer')!, {
    url: '/files/demo.pdf',
    options: {
    theme: 'light'
    }
    })

    传统页面也可使用IIFE产物,通过file-viewer-copy-assets把viewer assets发布到自己的静态目录,再用全局对象挂载。

    URL最简单,适合文件地址能被浏览器直接访问的场景:

    <FileViewer url="https://cdn.example.com/report.pdf" />

    本地上传、鉴权下载和SDK返回二进制时,推荐传File:

    constfile =newFile([blob],'contract.pdf', {
    type: blob.type
    })

    ArrayBuffer也建议先包装成带扩展名的File:

    const buffer = await sdk.downloadAttachment(id)
    const file = new File([buffer], 'report.xlsx')

    文件名很关键,预览器会根据扩展名选择渲染链路。遇到/download?id=123这种无后缀地址,推荐业务侧先下载,再补一个准确文件名。

    鉴权文件下载推荐方式

    const response = awaitfetch('/api/files/123/preview', {
    credentials: 'include',
    headers: {
    Authorization: `Bearer ${token}`
    }
    })

    const blob = await response.blob()
    const file = newFile([blob], 'sealed-contract.ofd', {
    type: blob.type
    })

    这样权限仍然由业务系统控制,预览器只负责浏览器端解析和展示。

    CAD、压缩包、PDF、Typst、SQLite、DOCX Worker等链路会按需使用Worker或WASM。内网、CSP严格、CDN子路径部署时,可显式配置资源地址:

    const options = {
    pdf: {
    workerUrl: '/file-viewer/vendor/pdf/pdf.worker.mjs',
    streaming: 'same-origin',
    rangeChunkSize: 64 * 1024
    },
    cad: {
    wasmPath: '/file-viewer/wasm/cad/',
    workerUrl: '/file-viewer/wasm/cad/dwg-worker.js',
    dwfWasmUrl: '/file-viewer/wasm/cad/dwfv-render.wasm'
    },
    archive: {
    workerUrl: '/file-viewer/vendor/libarchive/worker-bundle.js',
    workerTimeoutMs: 30000,
    cache: true
    },
    typst: {
    compilerWasmUrl: '/file-viewer/wasm/typst/typst_ts_web_compiler_bg.wasm',
    rendererWasmUrl: '/file-viewer/wasm/typst/typst_ts_renderer_bg.wasm'
    },
    data: {
    sqlWasmUrl: '/file-viewer/wasm/sql/sql-wasm.wasm'
    }
    }

    加载、卸载、打印、下载、导出、缩放都可接入业务审计和权限控制。

    const options = {
    hooks: {
    onLoadStart(ctx) {
    console.log('开始加载', ctx.type, ctx.filename)
    },
    onLoadComplete(ctx) {
    console.log('加载完成', ctx.duration)
    },
    onUnloadStart(ctx) {
    console.log('开始卸载', ctx.reason)
    },
    onUnloadComplete(ctx) {
    console.log('卸载完成', ctx.filename)
    }
    },
    asyncbeforeOperation(ctx) {
    if (ctx.operation === 'print') {
    returnawaitcheckPrintPermission(ctx.filename)
    }
    returntrue
    }
    }

    水印、打印、下载、导出HTML

    const options = {
    theme: 'light',
    toolbar: {
    position: 'bottom-right',
    download: true,
    print: true,
    exportHtml: true,
    zoom: true
    },
    watermark: {
    text: '内部资料',
    opacity: 0.16,
    rotate: 24,
    color: '#0f766e'
    }
    }

    打印会尽量只输出主体文档,不带Demo外壳。PDF和Word会按页面尺寸处理;Excel等虚拟表格链路会根据能力动态隐藏打印按钮,避免输出只有当前视口。

    预览器提供searchDocument()、nextSearchResult()、previousSearchResult()、collectDocumentAnchors()、scrollToLine()、scrollToAnchor()和getDocumentTextChunks()等能力。

    业务侧可把文本切片写入自己的向量库或审计系统,再通过锚点回到原文位置。File Viewer 本身只提供结构、定位和高亮能力,不绑定任何云端模型。

    文档比对是独立页面,适合合同版本、PDF与源文件、PPTX版本差异、Markdown与导出稿对照:https://demo.file-viewer.app/compare.html

    可预置左右文件:

    /compare.html?left=/example/pdf.pdf&right=/example/word.docx

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 文件预览服务:kkFileView、File Viewer
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!