# 文件预览 **Repository Path**: wb04307201/file-view ## Basic Information - **Project Name**: 文件预览 - **Description**: 一个轻量级文件预览的starter组件,支持多种文档和媒体格式的在线预览,采用模块化架构,易于扩展和定制 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 186 - **Forks**: 52 - **Created**: 2022-11-03 - **Last Updated**: 2026-05-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: 预览, 文档, Spring, OnlyOffice, minio ## README # File View 文件预览
English | 中文
> 一个 Spring Boot 3.x 的轻量级文件在线预览 Starter 组件,通过简单的 Maven 依赖引入即可为项目提供 docx/xlsx/pptx/PDF/BPMN/图片/视频/代码/3D 模型/CAD 等 20+ 种文件格式的在线预览能力。 ![Maven Central](https://img.shields.io/maven-central/v/io.github.wb04307201/file-view-spring-boot-starter?style=flat-square) [![star](https://gitee.com/wb04307201/file-view/badge/star.svg?theme=dark)](https://gitee.com/wb04307201/file-view) [![fork](https://gitee.com/wb04307201/file-view/badge/fork.svg?theme=dark)](https://gitee.com/wb04307201/file-view) [![star](https://img.shields.io/github/stars/wb04307201/file-view)](https://github.com/wb04307201/file-view) [![fork](https://img.shields.io/github/forks/wb04307201/file-view)](https://github.com/wb04307201/file-view) ![MIT](https://img.shields.io/badge/License-Apache2.0-blue.svg) ![JDK](https://img.shields.io/badge/JDK-17+-green.svg) ![SpringBoot](https://img.shields.io/badge/Spring%20Boot-3+-green.svg) --- ## 支持的文件类型 - office文件(docx,xlsx,xls,pptx) - 业务流程管理文件(bpmn,dmn,cmmn) - 图片文件 - 视频文件 - 音频文件 - 文档文件(pdf,epub,ofd) - TIFF图像文件 - 文本文件/代码文件(c,cpp,cs,css,diff,go,graphql,html,ini,java,js,json,kt,less,lua,m,pl,php,phtml,py,pyrepl,r,rb,rs,scss,sh,sql,swift,ts,vb,wasm,xml,yaml,yml) - Markdown文档文件 - 3D模型文件(3dm,3ds,3mf,amf,bim,brep,dae,fbx,fcstd,gltf,ifc,iges,step,stl,obj,off,ply,wrl) - 思维导图文件(xmind) - 压缩文件(zip) - CAD(dwg,dxf) ## 引入 ### 添加Maven依赖 ```xml io.github.wb04307201 file-view-spring-boot-starter 1.3.3 ``` ### 配置文件 ```yaml file: view: ## 以下为默认的处理器,默认无需配置 bpmn: enable: true dmn: enable: true cmmn: enable: true code: enable: true epub: enable: true image: enable: true markdown: enable: true pdf: enable: true xmind: enable: true docx: enable: true excel: enable: true pptx: enable: true o3d: enable: true zip: enable: true cad: enable: true csv: enable: true tiff: enable: true ofd: enable: true ## 以下为默认的文件名和处理器匹配规则,默认无需配置 strategies: - syntaxAndPattern: glob:*.bpmn serviceName: bpmn - syntaxAndPattern: glob:*.dmn serviceName: dmn - syntaxAndPattern: glob:*.cmmn serviceName: cmmn - syntaxAndPattern: glob:*.{c,cpp,cs,css,diff,go,graphql,html,ini,java,js,json,kt,less,lua,m,pl,php,phtml,py,pyrepl,r,rb,rs,scss,sh,sql,swift,ts,vb,wasm,xml,yaml,yml} serviceName: code - syntaxAndPattern: glob:*.epub serviceName: epub - syntaxAndPattern: glob:*.{jpg,png,bmp,gif,webp,svg,raw,heic,cr2,nef,orf,sr2} serviceName: image - syntaxAndPattern: glob:*.md serviceName: markdown - syntaxAndPattern: glob:*.pdf serviceName: pdf - syntaxAndPattern: glob:*.xmind serviceName: xmind - syntaxAndPattern: glob:*.docx serviceName: docx - syntaxAndPattern: glob:*.{xlsx,xls} serviceName: excel - syntaxAndPattern: glob:*.pptx serviceName: pptx - syntaxAndPattern: glob:*.{3dm,3ds,3mf,amf,bim,brep,dae,fbx,fcstd,gltf,ifc,iges,step,stl,obj,off,ply,wrl} serviceName: o3d - syntaxAndPattern: glob:*.zip serviceName: zip - syntaxAndPattern: glob:*.csv serviceName: csv - syntaxAndPattern: glob:*.{tif,tiff} serviceName: tiff - syntaxAndPattern: glob:*.ofd serviceName: ofd - syntaxAndPattern: glob:*.{dwg,dxf} serviceName: cad ``` `syntaxAndPattern`通过指定语法(如 glob 或 regex)对文件名进行匹配: - glob:`*.txt` - regex:`(.*)\.txt` ## 使用 ### 静态资源库 部分文件类型使用内置渲染器,如:pdf、epub、xmind、zip、image、code、markdown、cmmn、dmn、bpmn等 使用的js库资源从jsDelivr加载,如无法从jsDelivr获取资源,可以添加`file-view-static`将js库本地化 ```xml io.github.wb04307201 file-view-static 1.3.3 ``` ### 访问内置界面进行文件上传和预览 访问 `http://localhost:8080/file/view` ![img.png](img.png) ![gif.gif](gif.gif) ### 预览扩展 下面以OnlyOffice为例说明如何扩展预览: 1. 使用docker安装[OnlyOffice文档开发者版](https://api.onlyoffice.com/docs/docs-api/get-started/basic-concepts/) ```bash docker run --name onlyoffice -i -t -d -p 80:80 -e JWT_ENABLED=false -e ALLOW_PRIVATE_IP_ADDRESS=true onlyoffice/documentserver-de ``` 2. 文件预览渲染器扩展 编写`IView.java`接口的实现`OnlyOfficeView.java`: ```java package cn.wubo.file.view.test; import cn.wubo.file.view.preview.IView; import org.springframework.stereotype.Service; import org.springframework.web.servlet.function.ServerRequest; import org.springframework.web.servlet.function.ServerResponse; import java.net.URI; @Service public class OnlyOfficeView implements IView { @Override public String getServiceName() { return "onlyoffice"; } @Override public ServerResponse handle(ServerRequest request) { String id = request.pathVariable("id"); return ServerResponse.temporaryRedirect(URI.create(String.format("/onlyoffice.html?id=%s",id))).build(); } } ``` 编写页面`onlyoffice.html`: ```html onlyoffice
``` 3. 修改配置,关闭重复的渲染器,重定义文件匹配规则`application.yml`: ```yaml file: view: docx: enable: false excel: enable: false pptx: enable: false strategies: - ... # - syntaxAndPattern: glob:*.docx # serviceName: docx # - syntaxAndPattern: glob:*.xlsx # serviceName: excel # - syntaxAndPattern: glob:*.pptx # serviceName: pptx - syntaxAndPattern: glob:*.{docx,doc,xlsx,xls,pptx,ppt} serviceName: onlyoffice ``` 预览效果如下: ![gif_1.gif](gif_1.gif) ### 文件存储扩展 下面以MinIO为例说明如何扩展文件存储: 1. 使用docker安装MinIO: ```bash docker run -p 9000:9000 -p 9001:9001 --name minio -e "MINIO_ROOT_USER=ROOTUSER" -e "MINIO_ROOT_PASSWORD=CHANGEME123" quay.io/minio/minio server /data --console-address ":9001" ``` 2. 添加MinIO依赖: ```xml io.minio minio 8.6.0 ``` 3. 编写接口`IFileStorage.java`的实现`MinioFileStorageImpl.java`: ```java package cn.wubo.file.view.test; import cn.wubo.file.view.exception.LocalFileStorageException; import cn.wubo.file.view.storage.IFileStorage; import cn.wubo.file.view.storage.dto.FileStorageInfo; import cn.wubo.file.view.utils.VersionUtls; import io.minio.GetObjectArgs; import io.minio.MinioClient; import io.minio.PutObjectArgs; import io.minio.RemoveObjectArgs; import org.springframework.stereotype.Service; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.Path; import java.nio.file.Paths; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; import java.util.UUID; @Service public class MinioFileStorageImpl implements IFileStorage { private final MinioClient minioClient; private static final String BUCKET_NAME = "temp"; private static List fileStorageInfos = new ArrayList<>(); public MinioFileStorageImpl() { this.minioClient = new MinioClient.Builder() .endpoint("http://127.0.0.1:9000") .credentials("ROOTUSER", "12345678") .build(); } @Override public FileStorageInfo upload(String fileName, byte[] content, String mimeType) { try { String id = UUID.randomUUID().toString(); String version = VersionUtls.generateContentVersion(content, id); Path filePath = Paths.get(version, fileName); minioClient.putObject( PutObjectArgs.builder() .bucket(BUCKET_NAME) .object(filePath.toString()) .stream(new ByteArrayInputStream(content), content.length, -1) .contentType(mimeType) .build() ); FileStorageInfo fpi = new FileStorageInfo(id, fileName, content.length, mimeType, filePath.toString(), version); fileStorageInfos.add(fpi); return fpi; } catch (NoSuchAlgorithmException | IOException | InvalidKeyException | InvalidResponseException | InsufficientDataException | InternalException | ErrorResponseException | XmlParserException | ServerException e) { throw new LocalFileStorageException(e.getMessage(), e); } } @Override public FileStorageInfo findById(String id) { return fileStorageInfos.stream() .filter(fpi -> fpi.getId().equals(id)) .findAny() .orElseThrow(() -> new LocalFileStorageException("File info not found for id: " + id)); } @Override public List list() { return fileStorageInfos; } @Override public byte[] getContentByLocation(String location) { try { InputStream is = minioClient.getObject( GetObjectArgs.builder() .bucket(BUCKET_NAME) .object(location) .build() ); return is.readAllBytes(); } catch (IOException | InvalidKeyException | InvalidResponseException | NoSuchAlgorithmException | InsufficientDataException | InternalException | ErrorResponseException | XmlParserException | ServerException e) { throw new LocalFileStorageException(e.getMessage(), e); } } @Override public Boolean deleteById(String id) { FileStorageInfo fsi = findById(id); if (fsi != null) { try { minioClient.removeObject( RemoveObjectArgs.builder() .bucket(BUCKET_NAME) .object(fsi.getLocation()) .build() ); fileStorageInfos.remove(fsi); } catch (IOException | InvalidKeyException | InvalidResponseException | NoSuchAlgorithmException | InsufficientDataException | InternalException | ErrorResponseException | XmlParserException | ServerException e) { throw new LocalFileStorageException(e.getMessage(), e); } } return true; } } ``` ## 使用的第三方库 | 文件类型 | 第三方库 | |-------------------|---------------------------------------------------------------------------------------------------------------------------------------------| | DOCX 文件 | [docx-preview](https://github.com/VolodymyrBaydak/docx-preview) + [JSZip](https://github.com/Stuk/jszip) | | XLSX 文件 | [SheetJS](https://github.com/SheetJS/sheetjs) | | PPTX 文件 | [pptxviewjs](https://github.com/nicktomach/pptxviewjs) + [Chart.js](https://github.com/chartjs/Chart.js) | | 业务流程管理文件 | [bpmn-js](https://github.com/bpmn-io/bpmn-js) / [cmmn-js](https://github.com/bpmn-io/cmmn-js) / [dmn-js](https://github.com/bpmn-io/dmn-js) | | 图片文件 | [Viewer.js](https://github.com/fengyuanchen/viewerjs) | | 文档文件(PDF) | [PDFObject](https://github.com/pipwerks/PDFObject) | | 文档文件(EPUB) | [epub.js](https://github.com/futurepress/epub.js) + [JSZip](https://github.com/Stuk/jszip) | | 文本文件/代码文件 | [highlight.js](https://github.com/highlightjs/highlight.js) | | Markdown文档文件 | [Vditor](https://github.com/Vanessa219/vditor) | | CSV 文件 | [Papa Parse](https://github.com/mholt/PapaParse) | | 3D 模型文件 | [Online 3D Viewer](https://github.com/kovacsv/Online3DViewer) + [Three.js](https://github.com/mrdoob/three.js) | | 思维导图文件 | [xmind-embed-viewer](https://github.com/xmindltd/xmind-embed-viewer) | | 压缩文件 | [JSZip](https://github.com/Stuk/jszip) | | CAD 文件(DWG/DXF) | [@mlightcad/cad-simple-viewer](https://github.com/mlightcad/cad-viewer) + [Three.js](https://github.com/mrdoob/three.js) | | TIFF 图像文件 | [UTIF.js](https://github.com/photopea/UTIF.js) + [pako](https://github.com/nodeca/pako) | | OFD 文件 | [xq-doc-viewer](https://www.npmjs.com/package/xq-doc-viewer) |