文件预览服务:kkFileView、File Viewer

文件预览服务: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-processimm/action,param_value接口实例OSS域名/family.jpg?x-oss-processimm/detectfaceIMM基于x-oss-process推出全新的文档处理、音视频处理等能力支持样式、异步任务、批处理、触发器等多种使用方式。COS上传文件后有【预览】入口点击预览果不其然也是收费服务点击【开启服务】预览效果开源商业化平台能力是ok的但涉及到企业内部安全隐私数据泄密等问题最好还是使用本地化部署方案。本文收集几个基于浏览器的文件预览开源项目。kkFileView官网一个基于JavaSpring Boot的万能文件预览开源GitHub14.4K Star3.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地址既可实现在线预览如下图所示部署gitclone https://github.com/kekingcn/kkFileView.gitcdkkfileviewerdockerbuild-tkkfileview:v5.0.0.dockerrun-d-p8012:8012--namekkfileview kkfileview:v5.0.0打开http://localhost:8012开始体验。集成MinIO添加依赖implementation io.minio:minio:8.5.17application.yaml配置minio:endpoint:http://xxxxx:9000accessKey:xxxxsecretKey:xxxxxbucketName:testMinIO配置类ConfigurationpublicclassMinioConfig{Value(${minio.endpoint})privateStringendPoint;Value(${minio.accessKey})privateStringaccessKey;Value(${minio.secretKey})privateStringsecretKey;Value(${minio.bucketName})privateStringbucketName;BeanprotectedMinioClientminioClient(){returnMinioClient.builder().endpoint(endPoint).credentials(accessKey,secretKey).build();}}工具类ComponentpublicclassMinioUtils{Value(${minio.bucketName})privateStringbucketName;ResourceprivateMinioClientminioClient;publicApiResultuploadFile(MultipartFilefile)throwsAppException{StringfileNameSystem.currentTimeMillis()file.getOriginalFilename();try(InputStreamfifile.getInputStream()){PutObjectArgsputObjectArgsPutObjectArgs.builder().bucket(bucketName).contentType(file.getContentType()).object(fileName).stream(fi,fi.available(),-1).build();minioClient.putObject(putObjectArgs);}catch(Exceptione){thrownewAppException(文件上传失败e.getMessage());}returnApiResult.ok(fileName);}publicApiResultgetPreviewUrl(StringobjectName)throwsAppException{try{GetPresignedObjectUrlArgsurlArgsGetPresignedObjectUrlArgs.builder().bucket(bucketName).object(objectName).method(Method.GET).build();returnApiResult.ok(minioClient.getPresignedObjectUrl(urlArgs));}catch(Exceptione){thrownewAppException(获取预览链接失败e.getMessage());}}}controller接口类RestControllerRequestMapping(/file)publicclassFileOperationController{ResourceprivateMinioUtilsminioUtils;PostMapping(/upload)publicApiResultupload(MultipartFilefile)throwsAppException{returnminioUtils.uploadFile(file);}GetMapping(/getPreviewUrl)publicApiResultgetPreviewUrl(StringfileName)throwsAppException{returnminioUtils.getPreviewUrl(fileName);}}File Viewer官网全能、纯前端、开源GitHub1.8K Star185 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/XPSCAD 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、dotdocx-preview、msdoc-viewer合同、制度、报告、历史Word附件。复杂版式优先保持页面阅读效果Excel/表格xlsx、xlsm、xlsb、xls、csv、ods、fods、numbersstyled-exceljs虚拟表格业务台账、导出报表、多sheet文件。表格链路以交互查看为主PowerPointpptx、pptm、potx、ppsxaiden0z/pptx-renderer课件、方案、汇报材料。浏览器近似渲染复杂动画建议转PDF留档PDFpdfPDF.js合同、归档件、说明书。支持页导航、目录、缩放、搜索、打印和HTML导出OFDofdDLTech21/ofd.js发票、政企归档。按需加载OFD解析链路Typsttyp、typstTypst WASMSVG直接预览Typst源文件适合技术文档和排版稿CAD/图纸dwg、dxf、dwf、dwfx、xpsflyfish-dev/cad-viewerWASM/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.jsWorker兼容降级查看压缩包目录按需解压内部文档并继续预览邮件eml、msg、mboxpostal-mime、msgreader邮件归档、客服工单、附件审阅。正文隔离渲染附件可继续预览绘图excalidraw、drawio、dio官方Excalidraw/diagrams.net链路流程图、草图、架构图只读预览电子书epub、umdepubjs、UMD parser内部手册、电子书、历史移动阅读文件Markdown/代码md、json、js、ts、tsx、vue、py、java、sql、log等Markdownhighlight.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提供多条生产可用入口。新项目推荐优先使用标准包名历史包名继续保持兼容。技术栈技术栈推荐包名兼容包名适合场景Corefile-viewer/core无自研组件、底层能力、格式识别、生命周期和操作APIVue 3file-viewer/vue3flyfish-group/file-viewer3、file-viewer3Vue3中后台、知识库、合同系统Vue 2.7file-viewer/vue2.7flyfish-group/file-viewer存量Vue2.7项目Vue 2.6file-viewer/vue2.6无老Vue2.6项目React 18/19file-viewer/reactflyfish-group/file-viewer-reactReact中后台、SaaS、设计系统React 16.8/17file-viewer/react-legacy无老React项目纯Web/JSfile-viewer/webflyfish-group/file-viewer-web原生页面、Web Components外壳、微前端、script标签jQueryfile-viewer/jquery无老后台、CMS、传统页面Sveltefile-viewer/svelte无Svelte应用和组件库对于独立静态预览站可把自托管Demo页面放入业务iframe做隔离展示。新业务集成建议优先使用上面的原生组件或mountViewer调试体验和事件回调会更直接。实战安装pnpmaddfile-viewer/vue3# React、纯Web、jQuery、Svelte分别安装对应包pnpmaddfile-viewer/reactpnpmaddfile-viewer/webpnpmaddfile-viewer/jquerypnpmaddfile-viewer/svelteVue3示例script setup langtsimportFileViewerfromfile-viewer/vue3/scripttemplatediv styleheight: 100vhFileViewer url/files/demo.pdf//div/templateVue组件会自动带上样式父容器需要明确高度这是所有预览器最容易被忽略的基础条件。React示例importFileViewerfromfile-viewer/reactexportfunctionPreview(){return(div style{{height:100vh}}FileViewer url/files/contract.docx//div)}纯JS/Script标签import{mountViewer}fromfile-viewer/webconstcontrollermountViewer(document.getElementById(viewer)!,{url:/files/demo.pdf,options:{theme:light}})传统页面也可使用IIFE产物通过file-viewer-copy-assets把viewer assets发布到自己的静态目录再用全局对象挂载。URL最简单适合文件地址能被浏览器直接访问的场景FileViewer urlhttps://cdn.example.com/report.pdf/本地上传、鉴权下载和SDK返回二进制时推荐传FileconstfilenewFile([blob],contract.pdf,{type:blob.type})ArrayBuffer也建议先包装成带扩展名的Fileconstbufferawaitsdk.downloadAttachment(id)constfilenewFile([buffer],report.xlsx)文件名很关键预览器会根据扩展名选择渲染链路。遇到/download?id123这种无后缀地址推荐业务侧先下载再补一个准确文件名。鉴权文件下载推荐方式constresponseawaitfetch(/api/files/123/preview,{credentials:include,headers:{Authorization:Bearer${token}}})constblobawaitresponse.blob()constfilenewFile([blob],sealed-contract.ofd,{type:blob.type})这样权限仍然由业务系统控制预览器只负责浏览器端解析和展示。CAD、压缩包、PDF、Typst、SQLite、DOCX Worker等链路会按需使用Worker或WASM。内网、CSP严格、CDN子路径部署时可显式配置资源地址constoptions{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}}加载、卸载、打印、下载、导出、缩放都可接入业务审计和权限控制。constoptions{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.operationprint){returnawaitcheckPrintPermission(ctx.filename)}returntrue}}水印、打印、下载、导出HTMLconstoptions{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.pdfright/example/word.docx