查看原文
其他

基于 SpringBoot3.3 支持任意文件在线预览功能

编程疏影 路条编程
2024-09-05


基于 SpringBoot  支持任意文件在线预览功能

在现代Web应用中,文件的在线预览功能是一个非常重要的需求。通过在线预览,用户可以直接在浏览器中查看文件内容,无需下载到本地再打开。本文将详细介绍如何在SpringBoot项目中集成kkFileView,实现任意文件的在线预览功能。

kkFileView 是一款开源的文件在线预览工具,主要用于在Web应用中实现各种文件的在线预览功能。它基于Spring Boot进行开发,支持多种文件格式的预览,用户无需下载文件即可在浏览器中直接查看文件内容。

运行效果:

若想获取项目完整代码以及其他文章的项目源码,且在代码编写时遇到问题需要咨询交流,欢迎加入下方的知识星球。

kkFileView的主要特性:
  1. 多种文件格式支持:支持包括Office文档(Word、Excel、PowerPoint)、PDF、图片、文本文件、音视频文件等多种类型的文件预览。

  2. 高效的文件转换:利用Apache POI、PDFBox、Aspose等第三方库,实现文件的高效转换和预览。

  3. 集成简单:基于Spring Boot框架,提供了简单易用的API,方便与现有Spring Boot项目集成。

  4. 可定制性强:支持自定义预览模式,用户可以根据需求对预览效果进行个性化配置。

  5. 扩展性好:支持插件式扩展,可以轻松添加新的文件类型支持。

kkFileView支持的文件类型:
  1. 支持 doc, docx, xls, xlsx, xlsm, ppt, pptx, csv, tsv, dotm, xlt, xltm, dot, dotx,xlam, xla 等 Office 办公文档

  2. 支持 wps, dps, et, ett, wpt 等国产 WPS Office 办公文档

  3. 支持 odt, ods, ots, odp, otp, six, ott, fodt, fods 等OpenOffice、LibreOffice 办公文档

  4. 支持 vsd, vsdx 等 Visio 流程图文件

  5. 支持 wmf, emf 等 Windows 系统图像文件

  6. 支持 psd 等 Photoshop 软件模型文件

  7. 支持 pdf ,ofd, rtf 等文档

  8. 支持 xmind 软件模型文件

  9. 支持 bpmn 工作流文件

  10. 支持 eml 邮件文件

  11. 支持 epub 图书文档

  12. 支持 obj, 3ds, stl, ply, gltf, glb, off, 3dm, fbx, dae, wrl, 3mf, ifc, brep, step, iges, fcstd, bim 等 3D 模型文件

  13. 支持 dwg, dxf 等 CAD 模型文件

  14. 支持 txt, xml(渲染), md(渲染), java, php, py, js, css 等所有纯文本

  15. 支持 zip, rar, jar, tar, gzip, 7z 等压缩包

  16. 支持 jpg, jpeg, png, gif, bmp, ico, jfif, webp 等图片预览(翻转,缩放,镜像)

  17. 支持 tif, tiff 图信息模型文件

  18. 支持 tga 图像格式文件

  19. 支持 svg 矢量图像格式文件

  20. 支持 mp3,wav,mp4,flv 等音视频格式文件

  21. 支持 avi,mov,rm,webm,ts,rm,mkv,mpeg,ogg,mpg,rmvb,wmv,3gp,ts,swf 等视频格式转码预览

  22. 支持 dcm 等医疗数位影像预览

  23. 支持 drawio 绘图预览

kkFileView 安装

在开始 SpringBoot 项目之前,我们首先需要在服务器上安装 kkFileView。以下是详细的安装步骤:

  1. 下载 kkFileView 安装包

    首先,使用 wget 命令直接下载 kkFileView 4.0.0 的安装包:

    wget https://kkfileview.keking.cn/kkFileView-4.0.0.tar.gz
  2. 解压安装包

    下载完成后,使用以下命令解压安装包:

    tar -zxvf kkFileView-4.0.0.tar.gz
  3. 修改配置文件

    解压完成后,进入配置文件目录并修改 application.properties 配置文件:

    cd kkFileView-4.0.0/config
    vi application.properties

    将配置文件中的 server.address 修改为你当前虚拟机的 IP 地址。

  4. 启动 kkFileView

    进入 bin 目录,执行启动脚本启动 kkFileView:

    cd kkFileView-4.0.0/bin
    sh startup.sh

    启动后,可以通过以下命令查看日志,确认是否启动成功:

    sh showlog.sh

    如果日志中没有报错信息,则表示 kkFileView 已经成功启动。

项目结构

项目的基本结构如下:

├── src
│ ├── main
│ │ ├── java
│ │ │ └── com.icoderoad.filepreview
│ │ │ ├── controller
│ │ │ │ └── FileController.java
│ │ │ ├── config
│ │ │ │ └── WebConfig.java
│ │ │ ├── service
│ │ │ │ └── FileService.java
│ │ │ └── FilepreviewApplication.java
│ │ ├── resources
│ │ │ ├── templates
│ │ │ │ └── upload.html
│ │ │ │ └── preview.html
│ │ │ └── application.yml
│ └── pom.xml

引入依赖

首先,在 pom.xml 中添加kkFileView的依赖以及其他必要的依赖:

<dependencies>
<!-- Spring Boot 核心依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Thymeleaf 模板引擎 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<!-- 其他依赖 -->
</dependencies>

配置文件

在 application.yml 文件中,添加kkFileView相关配置:

server:
port: 8080

file-preview:
file-save-dir: /Users/icoderoad/code/java/filepreview/src/main/resources/uploadfile/ # 本地文件保存路径
base-url: http://localhost:8080/files # 文件的 HTTP 访问路径

后端代码实现

使用 WebMvcConfigurer 映射静态资源

你可以通过自定义 WebMvcConfigurer 来手动映射静态资源路径:

package com.icoderoad.filepreview.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

// 从配置文件中读取静态资源路径
@Value("${file-preview.file-save-dir}")
private String fileStoragePath;

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 映射资源路径
registry.addResourceHandler("/files/**")
.addResourceLocations("file:" + fileStoragePath);
}
}

这样就可以通过 http://localhost:8080/files/example.txt 来访问文件了。

主应用程序类 (FilepreviewApplication.java):

package com.icoderoad.filepreview;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class FilepreviewApplication {

public static void main(String[] args) {
SpringApplication.run(FilepreviewApplication.class, args);
}

}

文件服务类 (FileService.java):

package com.icoderoad.filepreview.service;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

@Service
public class FileService {

@Value("${file-preview.file-save-dir}")
private String fileSaveDir;

@Value("${file-preview.base-url}")
private String baseUrl;

public String saveFile(MultipartFile file) throws IOException {
// 创建文件保存路径
Path path = Paths.get(fileSaveDir, file.getOriginalFilename());
Files.write(path, file.getBytes());

// 生成文件的 HTTP URL
return baseUrl + "/" + file.getOriginalFilename();
}
}

文件预览控制器 (FileController.java):

package com.icoderoad.filepreview.controller;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import com.icoderoad.filepreview.service.FileService;

@Controller
public class FileController {

@Autowired
private FileService fileService;

@GetMapping("/")
public String index(Model model) {
return "upload";
}


@PostMapping("/upload")
public ResponseEntity<Map<String, String>> handleFileUpload(@RequestParam("file") MultipartFile file) {
Map<String, String> response = new HashMap<>();
try {
if (file.isEmpty()) {
throw new IllegalArgumentException("上传的文件为空");
}

// 保存文件并获取 HTTP 访问路径
String fileUrl = fileService.saveFile(file);
response.put("fileUrl", fileUrl);

return ResponseEntity.ok(response);
} catch (IOException e) {
e.printStackTrace();
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Map.of("error", "文件上传失败"));
}
}


@GetMapping("/preview")
public String previewFile(@RequestParam("filePath") String filePath, Model model) {
// 将文件路径传递给前端页面
model.addAttribute("filePath", filePath);
return "preview";
}
}

前端页面

文件上传页面 (upload.html):

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文件上传</title>
<!-- Bootstrap CSS -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
<style>
body {
padding-top: 20px;
}
.container {
max-width: 900px;
}
.upload-box {
border: 1px solid #ddd;
padding: 20px;
border-radius: 5px;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.progress {
margin-top: 10px;
}
.alert {
display: none; /* 默认隐藏提示信息 */
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-12">
<h1 class="text-center">文件上传</h1>
<div class="upload-box">
<form id="uploadForm" enctype="multipart/form-data">
<div class="form-group">
<label for="fileInput">选择文件</label>
<input type="file" class="form-control-file" id="fileInput" name="file">
</div>
<button type="submit" class="btn btn-primary">上传</button>
</form>
<div class="progress mt-3">
<div id="progressBar" class="progress-bar" role="progressbar" style="width: 0%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<div id="uploadStatus" class="alert alert-success mt-3"></div>
<div id="uploadError" class="alert alert-danger mt-3"></div>
<div id="previewSection" class="mt-3" style="display: none;">
<button id="previewButton" class="btn btn-success">查看预览</button>
</div>
</div>
</div>
</div>
</div>

<!-- Bootstrap JS and dependencies -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.2/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
<script>
$(document).ready(function() {
$('#uploadForm').on('submit', function(event) {
event.preventDefault(); // 防止默认提交

var formData = new FormData(this);

$.ajax({
url: '/upload', // 后端处理上传的接口
type: 'POST',
data: formData,
contentType: false,
processData: false,
xhr: function() {
var xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', function(e) {
if (e.lengthComputable) {
var percentComplete = Math.round((e.loaded / e.total) * 100);
$('#progressBar').css('width', percentComplete + '%');
$('#progressBar').attr('aria-valuenow', percentComplete);
}
}, false);
return xhr;
},
success: function(response) {
// 假设响应中包含文件的 URL
$('#uploadStatus').text('文件上传成功!').show();
$('#uploadError').hide();
$('#progressBar').css('width', '100%');

// 显示预览按钮
var fileUrl = response.fileUrl; // 从响应中获取文件 URL
console.log("fileUrl:", fileUrl);
$('#previewButton').data('file-url', fileUrl);
$('#previewSection').show();
},
error: function(xhr) {
$('#uploadError').text('文件上传失败!').show();
$('#uploadStatus').hide();
}
});

// 预览按钮点击事件
$('#previewButton').on('click', function() {
var fileUrl = $(this).data('file-url');
console.log("fileUrl:", fileUrl);
if (fileUrl) {
var previewUrl = 'http://localhost:8080/preview?filePath=' + encodeURIComponent(fileUrl);
window.open(previewUrl, '_blank');
}
});
});
});
</script>
</body>
</html>

文件预览页面 (preview.html):

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>File Preview</title>
<!-- Bootstrap CSS -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
<script type="text/javascript">
function base64Encode(str) {
return btoa(unescape(encodeURIComponent(str)));
}

</script>
<style>
body {
padding-top: 20px;
}
.container {
max-width: 900px;
}
.preview-box {
border: 1px solid #ddd;
padding: 20px;
border-radius: 5px;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
.iframe-container {
position: relative;
padding-top: 56.25%; /* 16:9 aspect ratio */
height: 0;
overflow: hidden;
}
.iframe-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>

<div class="container">
<div class="row">
<div class="col-md-12">
<h1 class="text-center">文件在线预览</h1>
<div class="preview-box">
<div class="iframe-container">
<!-- 使用 iframe 显示文件预览 -->
<script th:inline="javascript">
// 获取服务器传递的文件 HTTP 访问路径
var filePath = /*[[${filePath}]]*/ 'default.txt';
// 对文件路径进行 Base64 编码并进行 URL 编码
var encodedUrl =encodeURIComponent(base64Encode(filePath));
// 生成预览的 URL
var previewUrl = 'http://localhost:8012/onlinePreview?url=' + encodedUrl;
// 动态插入 iframe 用于文件预览
document.write('<iframe src="' + previewUrl + '" width="100%" height="600px"></iframe>');
</script>
</div>
</div>
</div>
</div>
</div>

</body>
</html>

启动项目

完成上述步骤后,启动Spring Boot项目,访问 http://localhost:8080,即可体验文件在线预览功能。

总结

通过本文的介绍,我们成功在Spring Boot项目中集成了kkFileView,实现了任意文件的在线预览功能。通过Spring Boot的简洁配置和kkFileView强大的文件解析能力,我们能够轻松地在Web应用中为用户提供优质的文件预览体验。


今天就讲到这里,如果有问题需要咨询,大家可以直接留言或扫下方二维码来知识星球找我,我们会尽力为你解答。


AI资源聚合站已经正式上线,该平台不仅仅是一个AI资源聚合站,更是一个为追求知识深度和广度的人们打造的智慧聚集地。通过访问 AI 资源聚合网站 https://ai-ziyuan.techwisdom.cn/,你将进入一个全方位涵盖人工智能和语言模型领域的宝藏库。


作者:路条编程(转载请获本公众号授权,并注明作者与出处)


继续滑动看下一个
路条编程
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存