文档在线预览在企业级应用开发也算是比较常遇见的需求了,通常处理这方面的需求大致有如下的方案,
1、购买成熟的第三方产品
比如永中DCS,其产品介绍可以查看如下链接
http://dcs.yozosoft.com/help.html
在比如idocv,其产品介绍可以查看如下链接
https://www.idocv.com/docs.html
2、自研实现文档预览服务器
标题取得高大上,常用的方法基本上也是基于第三方类库进行实现
3、文档预览是选择成熟第三产品还是自研?
如果公司成本预算充足,建议使用第三方成熟的产品,俗话说术业有专攻,正常专门做这方面的产品,不管是在技术上还是运维上都会比较成熟可靠,如果成本有限,还是自研吧,实现一个简单版本的文档预览服务器还是比较容易,但就是可能会采坑比较多。这边的选择只是针对文档预览,而非所有技术、产品选择都按这样选择,毕竟很多时候的自研的成本远远大于购买第三方服务,要具体情况具体分析
下边以jodconverter+LibreOffice为例,来实现一个简单的文档预览。这边为啥选LibreOffice而不选OpenOffice,其原因可以参考如下如下文章
OpenOffice与LibreOffice,哪个更适合你 https://www.linuxdashen.com/openoffice%E4%B8%8Elibreoffice%EF%BC%8C%E5%93%AA%E4%B8%AA%E6%9B%B4%E9%80%82%E5%90%88%E4%BD%A0 Apache OpenOffice 与 LibreOffice 之间的抉择 https://yq.aliyun.com/articles/81336
技术产品选型,可以从产品官方文档入手,产品的更新迭代活跃度、社区活跃度、是否易用等维度来进行考量,总归一句话不管黑猫白猫,能抓住老鼠的猫就是好猫,能够满足需求就行
1、window环境
可以通过下方链接下载,并按提示一步一步安装
https://zh-cn.libreoffice.org/download/download/
2、centos环境
#安装文件
yum -y install libreoffice
#安装中文包
yum -y install libreoffice-langpack-zh-Han*
#安装的目录在/usr/lib64/libreoffice
#centos
/usr/bin/libreoffice --invisible --convert-to pdf <待转换的word路径> --outdir <生成的pdf路径>
比如:/usr/bin/libreoffice --invisible --convert-to pdf test.txt --outdir abc
# windows
soffice.exe --headless --invisible --convert-to pdf test.txt --outdir d:\abc
1、pom.xml
<!-- office预览相关-->
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-core</artifactId>
</dependency>
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-local</artifactId>
</dependency>
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-online</artifactId>
</dependency>
<dependency>
<groupId>org.libreoffice</groupId>
<artifactId>ridl</artifactId>
</dependency>
2、application.yml
jodconverter:
local:
enabled: true
office-home: ${office.home}
port-numbers: 8100,8101,8102
max-tasks-per-process: 100
store:
path: ${store.path}
其中office.home和store.path,这两个属性一个是LibreOffice的安装路径,一个是LibreOffice转换后存放文档的路径,其中这两个属性的具体内容配置在pom.xml,内容如下
<profiles>
<profile>
<id>win</id>
<properties>
<office.home>D:/Program Files/LibreOffice</office.home>
<store.path>D:/data/preview</store.path>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>linux</id>
<properties>
<office.home>/usr/lib64/libreoffice</office.home>
<store.path>/data/preview</store.path>
</properties>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
</profiles>
通过maven的profile来指定环境,默认是window环境,如果要切换到linux环境,则打包是执行
mvn clean package -P linux
或者打包时,改下pom.xml,把默认环境切换为linux
3、转换文档的核心代码
@Service
@Slf4j
public class PreviewServiceImpl implements PreviewService {
@Value("${jodconverter.store.path}")
private String storePath;
@Autowired
private DocumentConverter documentConverter;
@Override
public FileConvertResultDTO convertFile2pdf(File sourceFile,String fileExt) {
FileConvertResultDTO fileConvertResultDTO = new FileConvertResultDTO();
try {
fileExt = fileExt.toLowerCase();
String fileName = FileUtil.getWithoutExtension(sourceFile.getName());
String targetFileExt = getTargetFileExt(fileExt);
File targetFile = new File(storePath+ FileUtil.SLASH_ONE + fileName + FileUtil.DOT + targetFileExt);
documentConverter.convert(sourceFile).as(DefaultDocumentFormatRegistry.getFormatByExtension(fileExt))
.to(targetFile).as(DefaultDocumentFormatRegistry.getFormatByExtension(targetFileExt)).execute();
fileConvertResultDTO.setStatus("success");
fileConvertResultDTO.setTargetFileName(targetFile.getName());
} catch (OfficeException e) {
log.error("convertFile2pdf error : " + e.getMessage(),e);
fileConvertResultDTO.setStatus("fail");
}
return fileConvertResultDTO;
}
@Override
public FileConvertResultDTO convertInputStream2pdf(InputStream in, String fileName, String fileExt) {
FileConvertResultDTO fileConvertResultDTO = new FileConvertResultDTO();
try {
fileExt = fileExt.toLowerCase();
fileName = FileUtil.getWithoutExtension(fileName);
String targetFileExt = getTargetFileExt(fileExt);
File targetFile = new File(storePath+ FileUtil.SLASH_ONE + fileName + FileUtil.DOT + targetFileExt);
documentConverter.convert(in).as(DefaultDocumentFormatRegistry.getFormatByExtension(fileExt))
.to(targetFile).as(DefaultDocumentFormatRegistry.getFormatByExtension(targetFileExt)).execute();
fileConvertResultDTO.setStatus("success");
fileConvertResultDTO.setTargetFileName(targetFile.getName());
} catch (OfficeException e) {
log.error("convertInputStream2pdf error : " + e.getMessage(),e);
fileConvertResultDTO.setStatus("fail");
}
return fileConvertResultDTO;
}
/**
* 获取想要转换的格式类型
* @return
*/
private String getTargetFileExt(String originFileExt){
if(Constants.fileType2Htmls.contains(originFileExt)){
return FileUtil.HTML;
}
return FileUtil.PDF;
}
@PostConstruct
private void init(){
File targetDir = new File(storePath);
if(!targetDir.exists()){
targetDir.mkdirs();
}
}
}
4、拉取office服务器文档代码
@GetMapping(value="/readFile")
public ResponseEntity<byte[]> readFile(String fileName){
if(StringUtils.isBlank(fileName)){
log.warn("fileName is blank");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
String fileExt = FileUtil.getExtension(fileName);
if(StringUtils.isBlank(fileExt)){
fileName = fileName + FileUtil.PDF;
}
String filePath = storePath + FileUtil.SLASH_ONE + fileName;
File file = new File(filePath);
if(!file.exists()){
log.warn("fileName:{} is not found",fileName);
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
try {
//判断文件类型
String mimeType = URLConnection.guessContentTypeFromName(file.getName());
if(mimeType == null) {
mimeType = "application/octet-stream";
}
response.setContentType(mimeType);
//设置文件响应大小
response.setContentLengthLong(file.length());
byte[] bytes = FileUtil.readFileToByteArray(file);
response.getOutputStream().write(bytes);
return new ResponseEntity<>(bytes,HttpStatus.OK);
} catch (IOException e) {
log.error("readFile error:"+e.getMessage(),e);
}
return new ResponseEntity<>(HttpStatus.EXPECTATION_FAILED);
}
5、测试验证
测试步骤按上方的流程图来测试 a、上传文档
b、点击确定按钮,进行跳转预览
https://www.libreofficechina.org/
文档在线预览方案
https://blog.csdn.net/xiaqingxue930914/article/details/81121581
SpringBoot使用LibreOffice转换PDF
https://segmentfault.com/a/1190000015129654
java版的office文档预览,本质上就利用jodconverter去连接openoffice或libreoffice服务,相当于我们自己实现的office服务器本质上算是一个openoffice或libreoffice代理服务器。在实现过程中,当excel转换pdf时,会存在一些坑点,比如excel的列的宽度大的时候生成的pdf会自动换行,有多个sheet页的时候默认也只能生成出来一个。解决的方案是,当遇到文档类型为excel时,就不要转换为pdf格式,而是转换为html格式
https://github.com/lyb-geek/springboot-learning/tree/master/springboot-office-preview