我是傲骄鹿先生,沉淀、学习、分享、成长。
如果你觉得文章内容还可以的话,希望不吝您的「一键三连」,文章里面有不足的地方希望各位在评论区补充疑惑、见解以及面试中遇到的奇葩问法
面对日常开发过程中,将各种文件转换为pdf文件的问题,总是让人头疼,这次终于完美解决了!
最好的效果无非就是在不限制文件大小、保持文件格式的情况下将文件转换为pdf格式文件,而且转换完成的文件不带水印,这样的效果应该可以满足很多需求了,之前在遇到这个问题的时候是使用spire.doc实现的,但效果很不好,每一页都是带水印的。下面将这是的方法展示给大家供大家参考。
一、集成aspose-words
实现文档转换为pdf文件需要的包是aspose-words-15.8.0,如果大家找不到包可以私信我,这里就不做链接了。
1、集成aspose-words-15.8.0
因为项目中使用的是阿里云的maven仓库,不能进行导包,就需要手动的将包导入到项目中。如图所示,将包放入到项目中。
包的位置是与src并列的位置,然后在pom文件中进行配置:
除了上面手动导入的包之外,还有其他用的包,在pom文件中添加即可。
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.4.3</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.docx4j</groupId>
<artifactId>docx4j</artifactId>
<version>3.2.2</version>
</dependency>
<!-- 下面的依赖是为了报其他错误的 -->
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>5.0.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.19</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.1</version>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>SparseBitSet</artifactId>
<version>1.2</version>
</dependency>
<!-- 修改com.aspose.cells专用包 -->
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.26.0-GA</version>
</dependency>
二、编写工具类
package com.dtech.common.utils.file;
import com.aspose.words.License;
import com.aspose.words.SaveFormat;
import com.itextpdf.text.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.xslf.usermodel.*;
import java.awt.*;
import java.awt.Font;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.List;
/**
* java将word、excel、ppt、图片转换为pdf文件
*/
public class PdfConverUtil {
/**
* @param inputStream 源文件输入流
* @param outputStream pdf文件输出流
**/
public static boolean imgToPdf(InputStream inputStream, OutputStream outputStream) {
Document document = null;
try {
// 创建文档,设置PDF页面的大小 A2-A9, 个人觉得A3最合适
document = new Document(PageSize.A3, 20, 20, 20, 20);
// 新建pdf文档,具体逻辑看.getInstance方法
PdfWriter.getInstance(document, outputStream);
document.open();
document.newPage();
// 将文件流转换为字节流,便于格式转换
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte[] bytes = new byte[1024];
int length = 0 ;
while (-1 != (length = bufferedInputStream.read(bytes))) {
byteArrayOutputStream.write(bytes, 0, length);
}
// 处理img图片
Image image = Image.getInstance(byteArrayOutputStream.toByteArray());
float height = image.getHeight();
float width = image.getWidth();
float percent = 0.0f;
// 设置像素或者长宽高,将会影响图片的清晰度,因为只是对图片放大或缩小
if (height > width) {
// A4 - A9
percent = PageSize.A4.getHeight() / height * 100;
} else {
percent = PageSize.A4.getWidth() / width * 100;
}
image.setAlignment(Image.MIDDLE);
image.scalePercent(percent);
// 将图片放入文档中,完成pdf转换
document.add(image);
// System.out.println("image转换完毕");
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
try {
if (document != null) {
document.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
return true;
}
/**
* @param inputStream 源文件输入流
* @param outputStream pdf文件输出流
**/
public static boolean wordTopdfByAspose(InputStream inputStream, OutputStream outputStream) {
// 验证License 若不验证则转化出的pdf文档会有水印产生
if (!getLicense()) {
return false;
}
try {
// 将源文件保存在com.aspose.words.Document中,具体的转换格式依靠里面的save方法
com.aspose.words.Document doc = new com.aspose.words.Document(inputStream);
// 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF,EPUB, XPS, SWF 相互转换
doc.save(outputStream, SaveFormat.PDF);
// System.out.println("word转换完毕");
} catch (Exception e) {
e.printStackTrace();
return false;
}finally {
if (outputStream != null) {
try {
outputStream.flush();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return true;
}
// 官方文档的要求 无需理会
public static boolean getLicense() {
boolean result = false;
try {
String s = "<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>";
ByteArrayInputStream is = new ByteArrayInputStream(s.getBytes());
License aposeLic = new License();
aposeLic.setLicense(is);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* @param inputStream 源文件输入流
* @param outputStream pdf文件输出流
**/
public static boolean excelToPdf(InputStream inputStream, OutputStream outputStream) {
// 验证License 若不验证则转化出的pdf文档会有水印产生
if (!getExeclLicense()) {
return false;
}
try {
com.aspose.cells.Workbook wb = new com.aspose.cells.Workbook(inputStream);// 原始excel路径
com.aspose.cells.PdfSaveOptions pdfSaveOptions = new com.aspose.cells.PdfSaveOptions();
pdfSaveOptions.setOnePagePerSheet(false);
int[] autoDrawSheets={3};
//当excel中对应的sheet页宽度太大时,在PDF中会拆断并分页。此处等比缩放。
autoDraw(wb,autoDrawSheets);
int[] showSheets={0};
//隐藏workbook中不需要的sheet页。
printSheetPage(wb,showSheets);
wb.save(outputStream, pdfSaveOptions);
outputStream.flush();
outputStream.close();
System.out.println("excel转换完毕");
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
/**
* 设置打印的sheet 自动拉伸比例
* @param wb
* @param page 自动拉伸的页的sheet数组
*/
public static void autoDraw(com.aspose.cells.Workbook wb,int[] page){
if(null!=page&&page.length>0){
for (int i = 0; i < page.length; i++) {
wb.getWorksheets().get(i).getHorizontalPageBreaks().clear();
wb.getWorksheets().get(i).getVerticalPageBreaks().clear();
}
}
}
/**
* 隐藏workbook中不需要的sheet页。
*
* @param wb
* @param page 显示页的sheet数组
*/
public static void printSheetPage(com.aspose.cells.Workbook wb, int[] page) {
for (int i = 1; i < wb.getWorksheets().getCount(); i++) {
wb.getWorksheets().get(i).setVisible(false);
}
if (null == page || page.length == 0) {
wb.getWorksheets().get(0).setVisible(true);
} else {
for (int i = 0; i < page.length; i++) {
wb.getWorksheets().get(i).setVisible(true);
}
}
}
public static boolean getExeclLicense() {
boolean result = false;
try {
String s = "<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>";
ByteArrayInputStream is = new ByteArrayInputStream(s.getBytes());
com.aspose.cells.License aposeLic = new com.aspose.cells.License();
aposeLic.setLicense(is);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* pptToPdf
* @param inputStream
* @param outputStream
* @return
*/
public static boolean pptToPdf(InputStream inputStream, OutputStream outputStream) {
Document document = null;
HSLFSlideShow hslfSlideShow = null;
PdfWriter pdfWriter = null;
try {
hslfSlideShow = new HSLFSlideShow(inputStream);
// 获取ppt文件页面
Dimension dimension = hslfSlideShow.getPageSize();
document = new Document();
// pdfWriter实例
pdfWriter = PdfWriter.getInstance(document, outputStream);
document.open();
PdfPTable pdfPTable = new PdfPTable(1);
List<HSLFSlide> hslfSlideList = hslfSlideShow.getSlides();
for (int i=0; i < hslfSlideList.size(); i++) {
HSLFSlide hslfSlide = hslfSlideList.get(i);
// 设置字体, 解决中文乱码
for (HSLFShape shape : hslfSlide.getShapes()) {
HSLFTextShape textShape = (HSLFTextShape) shape;
for (HSLFTextParagraph textParagraph : textShape.getTextParagraphs()) {
for (HSLFTextRun textRun : textParagraph.getTextRuns()) {
textRun.setFontFamily("宋体");
}
}
}
BufferedImage bufferedImage = new BufferedImage((int)dimension.getWidth(), (int)dimension.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2d = bufferedImage.createGraphics();
graphics2d.setPaint(Color.white);
graphics2d.setFont(new Font("宋体", Font.PLAIN, 12));
hslfSlide.draw(graphics2d);
graphics2d.dispose();
Image image = Image.getInstance(bufferedImage, null);
image.scalePercent(50f);
// 写入单元格
pdfPTable.addCell(new PdfPCell(image, true));
document.add(image);
}
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
if (document != null) {
document.close();
}
if (pdfWriter != null) {
pdfWriter.close();
}
}
// System.out.println("ppt转换完毕");
return true;
}
/**
* pptxToPdf
* @param inputStream
* @param outputStream
* @return
*/
public static boolean pptxToPdf(InputStream inputStream, OutputStream outputStream) {
Document document = null;
XMLSlideShow slideShow = null;
PdfWriter pdfWriter = null;
try {
slideShow = new XMLSlideShow(inputStream);
Dimension dimension = slideShow.getPageSize();
document = new Document();
pdfWriter = PdfWriter.getInstance(document, outputStream);
document.open();
PdfPTable pdfPTable = new PdfPTable(1);
List<XSLFSlide> slideList = slideShow.getSlides();
for (int i = 0, row = slideList.size(); i < row; i++) {
XSLFSlide slide = slideList.get(i);
// 设置字体, 解决中文乱码
for (XSLFShape shape : slide.getShapes()) {
XSLFTextShape textShape = (XSLFTextShape) shape;
for (XSLFTextParagraph textParagraph : textShape.getTextParagraphs()) {
for (XSLFTextRun textRun : textParagraph.getTextRuns()) {
textRun.setFontFamily("宋体");
}
}
}
BufferedImage bufferedImage = new BufferedImage((int)dimension.getWidth(), (int)dimension.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2d = bufferedImage.createGraphics();
graphics2d.setPaint(Color.white);
graphics2d.setFont(new Font("宋体", Font.PLAIN, 12));
slide.draw(graphics2d);
graphics2d.dispose();
Image image = Image.getInstance(bufferedImage, null);
image.scalePercent(50f);
// 写入单元格
pdfPTable.addCell(new PdfPCell(image, true));
document.add(image);
}
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
if (document != null) {
document.close();
}
if (pdfWriter != null) {
pdfWriter.close();
}
}
System.out.println("pptx转换完毕");
return true;
}
}
三、使用工具类进行文件转换
完成工具类编写就可以进行文件转换了,这里根据业务,将word文件进行上传服务器,然后在将服务器的word文件转换为pdf文件,访问端即可进行pdf文件预览了。
续:将代码打包上传至服务器后,转换完成的pdf文件是乱码
在window下没有问题但是在linux下有问题,说明不是代码或者输入输出流编码的问题,原因是两个平台环境的问题。说明linux环境中缺少相应的字体以供使用,可能会导致导出的文件字体乱码,或者更新域错乱问题。解决办法如下:更新字体
1、在linux环境下安装win字体,将win机器的C:\Windows\Fonts目录下的全部文件拷贝到linux服务器字体安装目录下,然后执行以下命令更新字体缓存。
2、linux服务器字体文件是在/usr/share/fonts文件夹下的,在fonts文件夹下新建一个文件夹chinese,然后把window环境中的字体上传到服务器中
3、执行命令,让字体生效
cd /usr/share/fonts
sudo fc-cache -fv
4、修改代码,设置字体
系列文章持续更新,微信搜一搜「傲骄鹿先生 」,回复【面试】有准备的一线大厂面试资料。