SpringBoot + LibreOffice + Hutool 实现附件预览简单示例

1. 简介

  在日常开发中,经常会遇到需要预览附件的需求,如果附件类型为图片、文本、PDF或者网页文件,则直接可以在浏览器预览;如果附件类型为Word、Excel、PPT等文件,则需要通过工具转换为PDF后在浏览器预览。
  本博客使用LibreOffice和Hutool实现文件预览简单示例。
  LibreOffice官网:https://zh-cn.libreoffice.org/

2. 安装Libreoffice

  • Windows安装
  • Linux安装
    • yum安装
    yum -y install libreoffice
    # 安装后的目录为:/usr/lib64/libreoffice
    
    • 乱码问题
    # 上传Windows的C:WindowsFonts目录中的字体到Linux的/usr/share/fonts/windows目录
    # 执行授权
    chmod 644 /usr/share/fonts/windows/* && fc-cache -fv
    
  • 官网安装手册
      https://zh-cn.libreoffice.org/get-help/install-howto/

3. 示例代码

  • 创建工程
  • 修改pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.c3stones</groupId>
	<artifactId>spring-boot-libreoffice-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-boot-libreoffice-demo</name>
	<description>Spring Boot Libreoffice Demo</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.4.RELEASE</version>
		<relativePath />
	</parent>

	<dependencies>
		<dependency>
			<groupId>org.jodconverter</groupId>
			<artifactId>jodconverter-spring-boot-starter</artifactId>
			<version>4.4.2</version>
		</dependency>
		<dependency>
			<groupId>org.jodconverter</groupId>
			<artifactId>jodconverter-local</artifactId>
			<version>4.4.2</version>
		</dependency>
		<dependency>
			<groupId>org.jodconverter</groupId>
			<artifactId>jodconverter-core</artifactId>
			<version>4.4.2</version>
		</dependency>
		<dependency>
			<groupId>org.libreoffice</groupId>
			<artifactId>ridl</artifactId>
			<version>7.2.0</version>
		</dependency>
		<dependency>
			<groupId>cn.hutool</groupId>
			<artifactId>hutool-all</artifactId>
			<version>5.7.13</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>
  • 创建配置文件application.yml
server:
  port: 8080

spring:
  thymeleaf:
    prefix: classpath:/view/
    suffix: .html
    encoding: UTF-8
    servlet:
      content-type: text/html
    cache: false
  servlet:
    multipart:
      max-file-size: 50MB
      max-request-size: 50MB

# 附件预览
jodconverter:
  local:
    enabled: true
#   # 设置LibreOffice目录
    officeHome: D:LibreOffice
#   # CentOS 下安装 LibreOffice:
#   # 1、安装:yum -y install libreoffice
#   # 2、配置:officeHome: /usr/lib64/libreoffice
#   # Linux 中文字体乱码解决:
#   # 1、上传 C:WindowsFonts 下的字体到 /usr/share/fonts/windows 目录
#   # 2、执行命令: chmod 644 /usr/share/fonts/windows/* && fc-cache -fv
#   # 监听端口,开启多个LibreOffice进程,每个端口对应一个进程
#   portNumbers: 8100,8101,8102
    portNumbers: 2002
#   # LibreOffice进程重启前的最大进程数
    maxTasksPerProcess: 10
#   # 任务在转换队列中的最大生存时间,默认30s
    taskQueueTimeout: 30
  • 创建Controller
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.servlet.http.HttpServletResponse;

import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.jodconverter.core.DocumentConverter;
import org.jodconverter.core.office.OfficeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;

/**
 * 附件预览Controller
 * 
 * @author CL
 *
 */
@Controller
@RequestMapping(value = "/file")
public class FilePreviewController {

	private static final Logger log = LoggerFactory.getLogger(FilePreviewController.class);

	@Autowired
	private DocumentConverter documentConverter;

	/**
	 * 跳转到附件预览和下载页面
	 * 
	 * @return
	 */
	@RequestMapping(value = "")
	public String index() {
		return "fileIndex";
	}

	/**
	 * 附件预览
	 * 
	 * @param file     附件
	 * @param response
	 */
	@RequestMapping(value = "/preview")
	@ResponseBody
	public void preview(MultipartFile file, HttpServletResponse response) {
		if (file == null) {
			return;
		}
		InputStream inputStream = null;
		OutputStream outputStream = null;
		try {
			inputStream = file.getInputStream();
			outputStream = response.getOutputStream();
			String fileName = file.getOriginalFilename();
			if (StrUtil.endWithAnyIgnoreCase(fileName, ".doc", ".docx", ".xls", ".xlsx", ".csv", ".ppt", ".pptx")) {
				// 转为PDF
				documentConverter.convert(inputStream).to(outputStream)
						.as(documentConverter.getFormatRegistry().getFormatByExtension("pdf")).execute();
			} else if (StrUtil.endWithAnyIgnoreCase(fileName, ".pdf", ".txt", ".xml", ".md", ".json", ".html", ".htm",
					".gif", ".jpg", ".jpeg", ".png", ".ico", ".bmp")) {
				IoUtil.copy(inputStream, outputStream);
			} else {
				outputStream.write("暂不支持预览此类型附件".getBytes());
			}
		} catch (IORuntimeException e) {
			log.error("附件预览IO运行异常:{}", e.getMessage());
		} catch (IOException e) {
			log.error("附件预览IO异常:{}", e.getMessage());
		} catch (OfficeException e) {
			log.error("附件预览Office异常:{}", e.getMessage());
		} finally {
			IOUtils.closeQuietly(inputStream);
		}
		IoUtil.writeUtf8(outputStream, true);
	}

}
  • 创建附件预览示例页面
      在resources下新建目录view,在view目录下新建页面:fileIndex.html
<html>
<head>
	<title>附件预览和下载</title>
</head>
<body>
	<h5>支持附件类型为:.doc, .docx, .xls, .xlsx, .csv, .ppt, .pptx, .pdf, .txt, .xml, .md, .json, .gif, .jpg, .jpeg, .png, .ico, .bmp</h5>
	<form id="fileForm" action="" method="post" enctype="multipart/form-data">
		<i style="color: red">*</i> 上传附件:<input id="file" name="file" type="file" /><br/>
	</form>
	<button onclick="preview()">预览</button>
</body>
</html>
<script>
// 预览方法
function preview() {
	// 检查是否为空和大小限制
	var file = document.getElementById('file').files[0];
	if (!file) {
		alert("附件不能为空");
		return;
	}
	var fileSize = file.size;
	if (fileSize > 50 * 1024 * 1024) {
		alert("最大支持附件大小为 50MB");
		return;
	}
	
	// 提交表单
	var fileForm = document.getElementById('fileForm');
	fileForm.action = "[[@{/}]]file/preview";  
	fileForm.submit();
}
</script>
  • 创建启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 启动类
 * 
 * @author CL
 *
 */
@SpringBootApplication
public class Application {

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

}

4. 测试

  • 启动项目
  • 浏览器访问:http://127.0.0.1:8080/file
  • 测试预览图片
  • 测试预览文本
  • 测试预览Word文件
  • 测试预览PPT文件
  • 测试预览PDF

5. 项目地址

  spring-boot-libreoffice-demo

原文地址:https://www.cnblogs.com/cao-lei/p/15406724.html