摘要:在项目过程中提出一个需要将doc在线预览并且要实现分页功能。
前端实现的缺点:1、只能预览docx文件,无法兼容doc,而且后端强制将doc转为docx的文件,前端也无法实现预览。2、前端无法进行分页展示。
一、后端实现需要引入jar包,以下是常用jar分析:
基于Openoffice | 基于libreOffice | 基于Office | 基于Pio+Itext | 基于Aspose | |
跨平台性 | 跨平台 | 跨平台 | 仅Windows | 跨平台 | 跨平台 |
是否安装软件 | 需安装Openoffice | 需安装libreOffice | 需安装MicrosoftOffice | 否 | 否 |
是否收费 | 免费 | 免费 | 软件收费 | 免费 | Jar包收费(可破解) |
优点 | 跨平台 文档转换失真小。 | 跨平台 转化相对快。 | 对于Office能很好保证少失真,特别是Word文档 跨平台 转换速度快。 | 支持跨平台。 | 不需要安装软件,失真情况较小。 |
缺点 | 需要安装额外软件 | 需要安装额外软件、效率较低 | 不跨平台需安装Office Office收费 Office版本不同效果不同(不稳定性) | 样式失真特别严重、效率极低。技术复杂 | 收费(但是可以破解)、即使付费,也不提供源码(官网) |
综合来看基于Aspose是最优方式,以下是实现方式。
二、实现
1、jar包引用
<!--文件转pdf工具类--> <dependency> <groupId>com.aspose</groupId> <artifactId>aspose-words</artifactId> <version>15.8.0</version> </dependency> <dependency> <groupId>com.aspose</groupId> <artifactId>aspose-cells</artifactId> <version>8.5.2</version> </dependency> <dependency> <groupId>com.aspose</groupId> <artifactId>aspose-slides</artifactId> <version>15.9.0</version> </dependency>
2、工具类
import com.aspose.cells.Workbook;
import com.aspose.slides.Presentation;
import com.aspose.words.Document;
import com.aspose.words.SaveFormat;
import java.io.*;
/**
* @Classname OnlinePreviewUtil
* @Description TODO
* @Date 2023/8/8 10:15
* @Created by laity2020
* @Author:Yan
*/
public class OnlinePreviewUtil {
/**
* 文件转换
*
* @param source:源文件地址 如:C://test/test.doc,target:转换后文件路径 如 C://test/pdf
* @return
*/
public static String officeToPdf(InputStream source, OutputStream target,String fileName) {
String fileExt = fileName.substring(fileName.lastIndexOf(".") + 1);
if ("doc".equals(fileExt) || "docx".equals(fileExt)) {
doc2pdf(source, target);
}
if ("xls".equals(fileExt) || "xlsx".equals(fileExt)) {
excel2pdf(source, target);
}
if ("ppt".equals(fileExt) || "pptx".equals(fileExt)) {
ppt2pdf(source, target);
}
if ("doc,docx,xls,xlsx,ppt,pptx".indexOf(fileExt) > 0) {
return target + File.separator + (fileName.replace(fileExt, "pdf"));
}
return null;
}
/**
* @description: 验证ExcelLicense
*/
public static boolean getExcelLicense() {
boolean result = false;
try {
// license.xml应放在..\WebRoot\WEB-INF\classes路径下
InputStream is = OnlinePreviewUtil.class.getClassLoader().getResourceAsStream("license.xml");
com.aspose.cells.License aposeLic = new com.aspose.cells.License();
aposeLic.setLicense(is);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* @description: 验证PPTtlLicense
*/
public static boolean getPPTLicense() {
boolean result = false;
try {
// license.xml应放在..\WebRoot\WEB-INF\classes路径下
InputStream is = OnlinePreviewUtil.class.getClassLoader().getResourceAsStream("license.xml");
com.aspose.slides.License aposeLic = new com.aspose.slides.License();
aposeLic.setLicense(is);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* @description: 验证License
*/
public static boolean getDocLicense() {
boolean result = false;
try {
// license.xml应放在..\WebRoot\WEB-INF\classes路径下
InputStream is = OnlinePreviewUtil.class.getClassLoader().getResourceAsStream("license.xml");
com.aspose.words.License aposeLic = new com.aspose.words.License();
aposeLic.setLicense(is);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* @description: doc转pdf
* @params: source:源文件,target:转换后文件
*/
public static void doc2pdf(InputStream source, OutputStream target) {
// 验证License 若不验证则转化出的pdf文档会有水印产生
if (!getDocLicense()) {
return;
}
try {
Document doc = new Document(source);
doc.save(target, com.aspose.words.SaveFormat.PDF);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @description: excel转pdf
* @params: source:源文件地址,target:转换后文件路径,fileExt:后缀
*/
public static void excel2pdf(InputStream source, OutputStream target) {
// 验证License 若不验证则转化出的pdf文档会有水印产生
if (!getExcelLicense()) {
return;
}
try {
// 原始excel路径
Workbook wb = new Workbook(source);
wb.save(target, com.aspose.cells.SaveFormat.PDF);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @description: ppt转pdf
* @params: source:源文件地址,target:转换后文件路径,fileExt:后缀
*/
public static void ppt2pdf(InputStream source, OutputStream target) {
// 验证License 若不验证则转化出的pdf文档会有水印产生
if (!getPPTLicense()) {
return;
}
try {
//输入pdf路径
Presentation pres = new Presentation(source);
pres.save(target, SaveFormat.PDF);
target.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
3、xml配置文件
<License>
<Data>
<Products>
<Product>Aspose.Total for Java</Product>
<Product>Aspose.Words for Java</Product>
</Products>
<EditionType>Enterprise</EditionType>
<SubscriptionExpiry>20991231</SubscriptionExpiry>
<LicenseExpiry>20991231</LicenseExpiry>
<SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
</Data>
<Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature>
</License>
4、调用方式,我采用的用文件流的形式,减少文件的生成。
OnlinePreviewUtil.officeToPdf(inputStream, outputStream(),realName);
注意:1、在这个过程中小编尝试了很多方法,因为本身项目采用了poi,引入dom4j、itextpdf和fr.opensagres.poi.xwpf.converter.pdf-gae时均因jar包冲突导致文件转pdf失败,以上是能完美实现并不poi不冲突的方式,遂进行记录。
2、windows部署正常但是linux下载后字体会乱码,是因为linux上无windows的字体导致的。解决方式如下:
1、将windows上的 C:\Windows\Fonts 的字体上传到linux的 /usr/share/fonts/ 目录下,然后在linux上执行
cd /usr/share/fonts/Chinese/
mkfontscale (创建字体的fonts.scale文件,它用来控制字体旋转缩放)
mkfontdir (创建字体的fonts.dir文件,它用来控制字体粗斜体产生)
fc-cache(刷新字体缓存)
最后在doc.save前加上 FontSettings.setFontsFolder("/usr/share/fonts/", true); 即可。