@

之前在写文档在线预览时留下了一个小坑,当时比较推荐的做法是将各种类型的文档都由后端统一转成pdf格式再由前端进行展示,但是当时并没有提供将各种类型的文档转pdf的方法,这次就来填一下这个坑。

前端在线预览pdf文件的实现方式可以参考这篇文章:《文档在线预览(三)使用js前端实现word、excel、pdf、ppt 在线预览》中 PDF文件实现前端预览 部分。

事前准备

代码基于 aspose-words(用于word、txt转pdf),itextpdf(用于ppt、图片、excel转pdf),所以事先需要在项目里下面以下依赖

1、需要的maven依赖

		<dependency>
<groupId>com.luhuiguo</groupId>
<artifactId>aspose-words</artifactId>
<version>23.1</version>
</dependency>
<!-- poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-excelant</artifactId>
<version>5.2.0</version>
</dependency>
<!-- itextpdf -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13.2</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>

2、后面用到的工具类代码:

package com.fhey.service.common.utils.file;

import cn.hutool.core.util.StrUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; /**
* @author fhey
* @date 2023-04-20 11:15:58
* @description: 文件工具类
*/
public class FileUtil {
private static final Logger logger = LoggerFactory.getLogger(FileUtil.class); //获取新文件的全路径
public static String getNewFileFullPath(String sourceFilePath, String destFilePath, String ext) {
File destFile = new File(destFilePath);
if (destFile.isFile()) {
return destFilePath;
}
File sourceFile = new File(sourceFilePath);
String sourceFileName = sourceFile.getName();
if (sourceFile.isFile()) {
return destFilePath + File.separator + sourceFileName.substring(0, sourceFileName.lastIndexOf(StrUtil.DOT)) + StrUtil.DOT + ext;
}
return destFilePath + File.separator + sourceFileName + StrUtil.DOT + ext;
} //判断文件是否是图片
public static boolean isImage(File file) throws IOException {
FileInputStream is = new FileInputStream(file);
byte[] bytes = new byte[8];
is.read(bytes);
is.close();
String type = bytesToHexString(bytes).toUpperCase();
if (type.contains("FFD8FF") //JPEG(jpg)
|| type.contains("89504E47") //PNG
|| type.contains("47494638") //GIF
|| type.contains("49492A00") //TIFF(tif)
|| type.contains("424D") //Bitmap(bmp)
) {
return true;
}
return false;
} //将文件头转换成16进制字符串
public static String bytesToHexString(byte[] src) {
StringBuilder builder = new StringBuilder();
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
builder.append(0);
}
builder.append(hv);
}
return builder.toString();
} }

一、word文件转pdf文件(支持doc、docx)

word转pdf的方法比较简单,aspose-words基本都被帮我们搞定了,doc、docx都能支持。

代码:

public static void wordToPdf(String wordPath, String pdfPath) throws Exception {
pdfPath = FileUtil.getNewFileFullPath(wordPath, pdfPath, "pdf");
File file = new File(pdfPath);
FileOutputStream os = new FileOutputStream(file);
Document doc = new Document(wordPath);
doc.save(os, com.aspose.words.SaveFormat.PDF);
}

验证代码:

public static void main(String[] args) throws Exception {
wordToPdf("D:\\书籍\\电子书\\其它\\《山海经》异兽图.docx", "D:\\test");
}

转换效果如下,格式、图文都没什么问题,doc、docx经过验证也都能转换成功

二、txt文件转pdf文件

txt文件转pdf文件代码直接复用word的即可

代码:

public static void txtToPdf(String txtPath, String pdfPath) throws Exception {
wordToPdf(txtPath, pdfPath);
}

验证代码:

public static void main(String[] args) throws Exception {
txtToPdf("D:\\书籍\\电子书\\国外名著\\君主论.txt", "D:\\test");
}

转换效果如下

三、PPT文件转pdf文件(支持ppt、pptx)

PPT文件转pdf文件,听说你们公司不让用ppt,那就让我们把ppt转成pdf再用吧。其实从这里开始代码就开始复杂起来了,这里用到了Apache poi、itextpdf、Graphics2D三个库,于是我结合这三个库同时兼容ppt、pptx写出了第一版代码

ppt转pdf第一版代码

public static void pptToPdf(String pptPath, String pdfPath) throws IOException {
pdfPath = FileUtil.getNewFileFullPath(pptPath, pdfPath, "pdf");
com.itextpdf.text.Document document = null;
FileOutputStream fileOutputStream = null;
PdfWriter pdfWriter = null;
try {
InputStream inputStream = Files.newInputStream(Paths.get(pptPath));
SlideShow<?, ?> slideShow;
String ext = pptPath.substring(pptPath.lastIndexOf("."));
if (ext.equals(".pptx")) {
slideShow = new XMLSlideShow(inputStream);
} else {
slideShow = new HSLFSlideShow(inputStream);
}
Dimension dimension = slideShow.getPageSize();
fileOutputStream = new FileOutputStream(pdfPath);
//document = new com.itextpdf.text.Document(new com.itextpdf.text.Rectangle((float) dimension.getWidth(), (float) dimension.getHeight()));
document = new com.itextpdf.text.Document();
pdfWriter = PdfWriter.getInstance(document, fileOutputStream);
document.open();
for (Slide<?, ?> slide : slideShow.getSlides()) {
// 设置字体, 解决中文乱码
setPPTFont(slide, "宋体");
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 java.awt.Font("宋体", java.awt.Font.PLAIN, 12));
slide.draw(graphics2d);
graphics2d.dispose();
com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance(bufferedImage, null);
image.scaleToFit((float) dimension.getWidth(), (float) dimension.getHeight());
document.add(image);
document.newPage();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (document != null) {
document.close();
}
if (fileOutputStream != null) {
fileOutputStream.close();
}
if (pdfWriter != null) {
pdfWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
} private static void setPPTFont(Slide<?, ?> slide, String fontFamily) {
// 设置字体, 解决中文乱码
for (Shape<?, ?> shape : slide.getShapes()) {
if (shape instanceof TextShape) {
TextShape textShape = (TextShape) shape;
List<TextParagraph> textParagraphs = textShape.getTextParagraphs();
for (TextParagraph textParagraph : textParagraphs) {
List<TextRun> textRuns = textParagraph.getTextRuns();
for (TextRun textRun : textRuns) {
textRun.setFontFamily(fontFamily);
}
}
}
}
}

验证代码:

public static void main(String[] args) throws Exception {
pptToPdf("C:\\Users\\jie\\Desktop\\预览\\web\\files\\河西走廊见闻录.pptx", "D:\\test");
}

转换效果如下

可以看到转换效果并不怎么好,ppt的内容展示不全。于是我开始在网上找解决方案,结果找到了一个很神奇的解决方案,就绘制的图片先写在一个PdfPTable对象上,再把PdfPTable对象放到document离去,于是我根据这个改了改代码写出了第二版代码

ppt转pdf第二版代码

public static void pptToPdf(String pptPath, String pdfPath) throws IOException {
pdfPath = FileUtil.getNewFileFullPath(pptPath, pdfPath, "pdf");
com.itextpdf.text.Document document = null;
FileOutputStream fileOutputStream = null;
PdfWriter pdfWriter = null;
try {
InputStream inputStream = Files.newInputStream(Paths.get(pptPath));
SlideShow<?, ?> slideShow;
String ext = pptPath.substring(pptPath.lastIndexOf("."));
if (ext.equals(".pptx")) {
slideShow = new XMLSlideShow(inputStream);
} else {
slideShow = new HSLFSlideShow(inputStream);
}
Dimension dimension = slideShow.getPageSize();
fileOutputStream = new FileOutputStream(pdfPath);
//document = new com.itextpdf.text.Document(new com.itextpdf.text.Rectangle((float) dimension.getWidth(), (float) dimension.getHeight()));
document = new com.itextpdf.text.Document();
pdfWriter = PdfWriter.getInstance(document, fileOutputStream);
document.open();
PdfPTable pdfPTable = new PdfPTable(1);
for (Slide<?, ?> slide : slideShow.getSlides()) {
// 设置字体, 解决中文乱码
setPPTFont(slide, "宋体");
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 java.awt.Font("宋体", java.awt.Font.PLAIN, 12));
slide.draw(graphics2d);
graphics2d.dispose();
com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance(bufferedImage, null);
image.scaleToFit((float) dimension.getWidth(), (float) dimension.getHeight());
// 写入单元格
pdfPTable.addCell(new PdfPCell(image, true));
document.add(pdfPTable);
pdfPTable.deleteBodyRows();
document.newPage();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (document != null) {
document.close();
}
if (fileOutputStream != null) {
fileOutputStream.close();
}
if (pdfWriter != null) {
pdfWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

转换效果如下

可以看到ppt内容已经展示完整了,到此其实ppt转pdf功能已经基本实现了,但是显示效果依然不算完美毕竟我们其实想要的是在pdf里和在ppt看的是一样的效果,而且每页ppt的长宽其实都是一样的,所以我就在想能不能设置pdf每页的长宽,把pdf每页的长宽设置成和ppt的长宽一样。于是我开始看初始化pdf document的源码配置

com.itextpdf.text.Document document = new com.itextpdf.text.Document();

然后发现com.itextpdf.text.Document除了默认的构造函数外还有这这样一个构造函数:

public Document(Rectangle pageSize) {
this(pageSize, 36.0F, 36.0F, 36.0F, 36.0F);
}

然后com.itextpdf.text.Rectangle类点进去就发现了可以设置长宽的构造函数:

public Rectangle(float urx, float ury) {
this(0.0F, 0.0F, urx, ury);
}

于是我代码中的初始化Document进行如下调整(根据第一版代码改,第二版的PdfPTable可以不用了)

document = new com.itextpdf.text.Document();
//改成如下
document = new com.itextpdf.text.Document(new com.itextpdf.text.Rectangle((float) dimension.getWidth(), (float) dimension.getHeight()));

ppt转pdf第三版代码(最终版)

public static void pptToPdf(String pptPath, String pdfPath) throws IOException {
pdfPath = FileUtil.getNewFileFullPath(pptPath, pdfPath, "pdf");
com.itextpdf.text.Document document = null;
FileOutputStream fileOutputStream = null;
PdfWriter pdfWriter = null;
try {
InputStream inputStream = Files.newInputStream(Paths.get(pptPath));
SlideShow<?, ?> slideShow;
String ext = pptPath.substring(pptPath.lastIndexOf("."));
if (ext.equals(".pptx")) {
slideShow = new XMLSlideShow(inputStream);
} else {
slideShow = new HSLFSlideShow(inputStream);
}
Dimension dimension = slideShow.getPageSize();
fileOutputStream = new FileOutputStream(pdfPath);
//document = new com.itextpdf.text.Document();
document = new com.itextpdf.text.Document(new com.itextpdf.text.Rectangle((float) dimension.getWidth(), (float) dimension.getHeight()));
pdfWriter = PdfWriter.getInstance(document, fileOutputStream);
document.open();
for (Slide<?, ?> slide : slideShow.getSlides()) {
// 设置字体, 解决中文乱码
setPPTFont(slide, "宋体");
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 java.awt.Font("宋体", java.awt.Font.PLAIN, 12));
slide.draw(graphics2d);
graphics2d.dispose();
com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance(bufferedImage, null);
image.scaleToFit((float) dimension.getWidth(), (float) dimension.getHeight());
document.add(image);
document.newPage();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (document != null) {
document.close();
}
if (fileOutputStream != null) {
fileOutputStream.close();
}
if (pdfWriter != null) {
pdfWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

转换效果如下

现在展示的效果已经和ppt上一样了,而且经过验证ppt和pptx都是可以转换成功的。

四、图片转pdf文件

图片转pdf用到了用到了Apache poi、itextpdf两个库,因为itextpdf支持解析的图片有限,点开c读取图片的方法com.itextpdf.text.Image.getInstance,我们可以看到这样一段源码:

 Image img;
if (c1 == 71 && c2 == 73 && c3 == 70) {
GifImage gif = new GifImage(url);
img = gif.getImage(1);
img = img;
return img;
} if (c1 == 255 && c2 == 216) {
Jpeg var39 = new Jpeg(url);
return var39;
} Jpeg2000 var38;
if (c1 == 0 && c2 == 0 && c3 == 0 && c4 == 12) {
var38 = new Jpeg2000(url);
return var38;
} if (c1 == 255 && c2 == 79 && c3 == 255 && c4 == 81) {
var38 = new Jpeg2000(url);
return var38;
} if (c1 == PngImage.PNGID[0] && c2 == PngImage.PNGID[1] && c3 == PngImage.PNGID[2] && c4 == PngImage.PNGID[3]) {
var12 = PngImage.getImage(url);
return var12;
} if (c1 == 215 && c2 == 205) {
ImgWMF var37 = new ImgWMF(url);
return var37;
} if (c1 != 66 || c2 != 77) {
RandomAccessFileOrArray ra;
String file;
if (c1 == 77 && c2 == 77 && c3 == 0 && c4 == 42 || c1 == 73 && c2 == 73 && c3 == 42 && c4 == 0) {
ra = null; try {
if (url.getProtocol().equals("file")) {
file = url.getFile();
file = Utilities.unEscapeURL(file);
ra = new RandomAccessFileOrArray(randomAccessSourceFactory.createBestSource(file));
} else {
ra = new RandomAccessFileOrArray(randomAccessSourceFactory.createSource(url));
} img = TiffImage.getTiffImage(ra, 1);
img.url = url;
img = img;
return img;
} catch (RuntimeException var32) {
if (recoverFromImageError) {
img = TiffImage.getTiffImage(ra, recoverFromImageError, 1);
img.url = url;
Image var15 = img;
return var15;
} throw var32;
} finally {
if (ra != null) {
ra.close();
} }
} if (c1 == 151 && c2 == 74 && c3 == 66 && c4 == 50 && c5 == 13 && c6 == 10 && c7 == 26 && c8 == 10) {
ra = null; try {
if (url.getProtocol().equals("file")) {
file = url.getFile();
file = Utilities.unEscapeURL(file);
ra = new RandomAccessFileOrArray(randomAccessSourceFactory.createBestSource(file));
} else {
ra = new RandomAccessFileOrArray(randomAccessSourceFactory.createSource(url));
} img = JBIG2Image.getJbig2Image(ra, 1);
img.url = url;
img = img;
return img;
} finally {
if (ra != null) {
ra.close();
} }
}

由此可以可知itextpdf支持解析的图片只有gif、jpeg、png、bmp、wmf、tiff、 jbig2这几种,这些其实已经基本包含了所有主流的图片格式(百度图片:所以我用的webp格式是非主流格式?),而且图片格式不是光改后缀就行的,必须要用格式转换器转换。比如下面这张图虽然后缀是jpeg,但通过查看图片信息可知实际格式是webg格式itextpdf一样无法解析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BjLHOWSY-1685380307992)(C:\Users\jie\Desktop\文章\转pdf\pic\改后缀.png)]

话不多说我们先结合Apache poi、itextpdf两个库简单协议版基本的图片转换pdf代码

单图片转pdf第一版代码

public static void imageToPdf(String imgPath, String pdfPath) throws Exception {
pdfPath = FileUtil.getNewFileFullPath(imgPath, pdfPath, "pdf");
com.itextpdf.text.Document document = new com.itextpdf.text.Document();
PdfWriter.getInstance(document, Files.newOutputStream(Paths.get(pdfPath)));
document.open();
com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance(imgPath);
image.setAlignment(com.itextpdf.text.Image.ALIGN_CENTER);
document.add(image);
document.close();
}

验证代码:

public static void main(String[] args) throws Exception {
imageToPdf("D:\\picture\\美女\\aa37a7be4196c07f43a3f776801d1b46.jpg", "D:\\test");
}

转换效果如下

从效果可以我们可以看到这个图片其实是没有显示完全的, 其实小一点的图片是没什么问题的,但是因为pdf设置的每页都是A4大小,所以在图片过大时会显示不完整,所以我们在图片过大时需要对图片进行一些调整,调整后的代码如下:

单图片转pdf第二版代码

public static void imageToPdf(String imgPath, String pdfPath) throws Exception {
pdfPath = FileUtil.getNewFileFullPath(imgPath, pdfPath, "pdf");
com.itextpdf.text.Document document = new com.itextpdf.text.Document();
PdfWriter.getInstance(document, Files.newOutputStream(Paths.get(pdfPath)));
document.open();
com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance(imgPath);
float width = image.getWidth();
float height = image.getHeight();
float space = 50f;
if (width > PageSize.A4.getWidth() - space || height > PageSize.A4.getHeight() - space) {
image.scaleToFit(PageSize.A4.getWidth() - space, PageSize.A4.getHeight() - space);
}
image.setAlignment(com.itextpdf.text.Image.ALIGN_CENTER);
document.add(image);
document.close();
}

转换效果如下

可以看到现在图片已经完整的显示在pdf的页面中了,到这里你可能会有一个疑惑,为什么这次不想上面ppt转换pdf一样把pdf的页面长宽设置成和图片一样,而且去调整图片的大小呢。之所以这样做的原因是因为在接下来的多图片转换成一个pdf文件时,往往是不能确保每张图片的长宽比例是一样的,为了确保每张图片都能完整的显示,所以只能调整图片的大小。

将文件夹下的所有图片导成一个pdf

将图片一张一张的导成pdf毕竟很麻烦,比如我一个文件夹下面有很多张图片,我想将该文件夹下的所有图片都导入pdf中做个《美人谱》,我该怎么做呢?安排!于是代码调整成了下面这样

支持多图片转pdf代码:

public static void imageToPdf(String imagePath, String pdfPath) throws Exception {
pdfPath = FileUtil.getNewFileFullPath(imagePath, pdfPath, "pdf");
File imageFile = new File(imagePath);
File[] files;
if (imageFile.isDirectory()) {
files = imageFile.listFiles();
} else {
files = new File[]{imageFile};
}
imageToPdf(files, pdfPath);
} public static void imageToPdf(File[] imageFiles, String pdfPath) throws Exception {
com.itextpdf.text.Document document = new com.itextpdf.text.Document();
PdfWriter.getInstance(document, Files.newOutputStream(Paths.get(pdfPath)));
document.open();
for (File file : imageFiles) {
if (file.isFile() && FileUtil.isImage(file)) {
try {
com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance(file.getAbsolutePath());
float width = image.getWidth();
float height = image.getHeight();
float space = 10f;
if (width > PageSize.A4.getWidth() - space || height > PageSize.A4.getHeight() - space) {
image.scaleToFit(PageSize.A4.getWidth() - space, PageSize.A4.getHeight() - space);
}
image.setAlignment(com.itextpdf.text.Image.ALIGN_CENTER);
//document.setMargins(50, 150, 50, 50);
//document.setPageSize(new com.itextpdf.text.Rectangle(width, height));
document.newPage();
document.add(image);
} catch (Exception e) {
logger.error("图片转换失败", e);
}
}
}
document.close();
}

验证代码:

public static void main(String[] args) throws Exception {
imageToPdf("D:\\picture\\美女", "D:\\test\\美人谱.pdf");
}

转换效果如下

五、excel文件转pdf文件

其实excel转pdf在实际的应用场景中应该比较罕见,但是前面也说了这么多文件转pdf的方式了,那excel转pdf也就一并说说吧。

方式1 使用itextpdf

代码如下:

public static void excelToPdf(String excelPath, String pdfPath) throws DocumentException, IOException {
pdfPath = FileUtil.getNewFileFullPath(excelPath, pdfPath, "pdf");
try (Workbook workbook = WorkbookFactory.create(new File(excelPath))) {
com.itextpdf.text.Document document = new com.itextpdf.text.Document();
PdfWriter.getInstance(document, new FileOutputStream(pdfPath));
document.open();
BaseFont chineseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
Font font = new Font(chineseFont, 12, Font.NORMAL);
DecimalFormat df = new DecimalFormat("#");
for (Sheet sheet : workbook) {
PdfPTable table = new PdfPTable(sheet.getRow(0).getPhysicalNumberOfCells());
for (Row row : sheet) {
for (Cell cell : row) {
if (cell.getCellType() == CellType.NUMERIC) {
PdfPCell pdfPCell = new PdfPCell(new Paragraph(df.format(cell.getNumericCellValue()), font));
table.addCell(pdfPCell);
} else {
PdfPCell pdfPCell = new PdfPCell(new Paragraph(cell.toString(), font));
table.addCell(pdfPCell);
}
}
}
table.setHeaderRows(1);
document.add(table);
}
document.close();
}
}

验证代码:

public static void main(String[] args) throws Exception {
excelToPdf("C:\\Users\\jie\\Desktop\\新建 Microsoft Excel 工作表.xlsx", "D:\\test");
}

转换效果如下

方式2 使用spire

因为spire不在maven中央仓库里以及阿里云的maven仓库中,所以在使用spire之前需要现在maven中配置新的maven仓库地址,配置如下;

<repositories>
<repository>
<id>com.e-iceblue</id>
<name>e-iceblue</name>
<url>https://repo.e-iceblue.cn/repository/maven-public/</url>
</repository>
</repositories>

然后再pom中引入依赖:

收费:

<groupId>e-iceblue</groupId>
<artifactId>spire.office</artifactId>
<version>5.3.1</version>
</dependency>

或者 免费的:

<groupId>e-iceblue</groupId>
<artifactId>spire.office.free</artifactId>
<version>5.3.1</version>
</dependency>

免费版本基础功能都能用

代码:

public static void excelToPdf2(String excelPath, String pdfPath) throws DocumentException, IOException, InvalidFormatException {
pdfPath = FileUtil.getNewFileFullPath(excelPath, pdfPath, "pdf");
com.spire.xls.Workbook wb = new com.spire.xls.Workbook();
wb.loadFromFile(excelPath);
wb.saveToFile(pdfPath, com.spire.xls.FileFormat.PDF);
}

验证代码:

public static void main(String[] args) throws Exception {
excelToPdf2("C:\\Users\\jie\\Desktop\\新建 Microsoft Excel 工作表.xlsx", "D:\\test");
}

转换效果如下

工具类整体代码

好了到这里就已经将word、txt、ppt、excel、图片等文件转成pdf文件实现方式已经全部说完了,感谢阅读到这里的朋友!最后附上文中用到的工具类的整体代码:

package com.fhey.service.common.utils.file;

import cn.hutool.core.util.StrUtil;
import com.aspose.words.Document;
import com.fhey.service.common.utils.FileUtil;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import org.apache.poi.hslf.usermodel.*;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.sl.usermodel.Shape;
import org.apache.poi.sl.usermodel.*;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xslf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.Color;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.DecimalFormat;
import java.util.List; public class FileConvertUtil {
private static final Logger logger = LoggerFactory.getLogger(FileConvertUtil2.class); //将word转成pdf
public static void wordToPdf(String wordPath, String pdfPath) throws Exception {
pdfPath = FileUtil.getNewFileFullPath(wordPath, pdfPath, "pdf");
File file = new File(pdfPath);
FileOutputStream os = new FileOutputStream(file);
Document doc = new Document(wordPath);
doc.save(os, com.aspose.words.SaveFormat.PDF);
} //将txt转成pdf
public static void txtToPdf(String txtPath, String pdfPath) throws Exception {
wordToPdf(txtPath, pdfPath);
} //将图片转成pdf
public static void imageToPdf(String imagePath, String pdfPath) throws Exception {
pdfPath = FileUtil.getNewFileFullPath(imagePath, pdfPath, "pdf");
File imageFile = new File(imagePath);
File[] files;
if (imageFile.isDirectory()) {
files = imageFile.listFiles();
} else {
files = new File[]{imageFile};
}
imageToPdf(files, pdfPath);
} //将图片转成pdf
public static void imageToPdf(File[] imageFiles, String pdfPath) throws Exception {
com.itextpdf.text.Document document = new com.itextpdf.text.Document();
PdfWriter.getInstance(document, Files.newOutputStream(Paths.get(pdfPath)));
document.open();
for (File file : imageFiles) {
if (file.isFile() && FileUtil.isImage(file)) {
try {
com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance(file.getAbsolutePath());
float width = image.getWidth();
float height = image.getHeight();
float space = 10f;
if (width > PageSize.A4.getWidth() - space || height > PageSize.A4.getHeight() - space) {
image.scaleToFit(PageSize.A4.getWidth() - space, PageSize.A4.getHeight() - space);
}
image.setAlignment(com.itextpdf.text.Image.ALIGN_CENTER);
//document.setMargins(50, 150, 50, 50);
//document.setPageSize(new com.itextpdf.text.Rectangle(width, height));
document.newPage();
document.add(image);
} catch (Exception e) {
logger.error("图片转换失败", e);
}
}
}
document.close();
} //将excel文件转成pdf
public static void excelToPdf(String excelPath, String pdfPath) throws DocumentException, IOException {
pdfPath = FileUtil.getNewFileFullPath(excelPath, pdfPath, "pdf");
try (Workbook workbook = WorkbookFactory.create(new File(excelPath))) {
com.itextpdf.text.Document document = new com.itextpdf.text.Document();
PdfWriter.getInstance(document, new FileOutputStream(pdfPath));
document.open();
BaseFont chineseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
Font font = new Font(chineseFont, 12, Font.NORMAL);
DecimalFormat df = new DecimalFormat("#");
for (Sheet sheet : workbook) {
PdfPTable table = new PdfPTable(sheet.getRow(0).getPhysicalNumberOfCells());
for (Row row : sheet) {
for (Cell cell : row) {
if (cell.getCellType() == CellType.NUMERIC) {
PdfPCell pdfPCell = new PdfPCell(new Paragraph(df.format(cell.getNumericCellValue()), font));
table.addCell(pdfPCell);
} else {
PdfPCell pdfPCell = new PdfPCell(new Paragraph(cell.toString(), font));
table.addCell(pdfPCell);
}
}
}
table.setHeaderRows(1);
document.add(table);
}
document.close();
}
} //将excel文件转成pdf
public static void excelToPdf2(String excelPath, String pdfPath) throws DocumentException, IOException, InvalidFormatException {
pdfPath = FileUtil.getNewFileFullPath(excelPath, pdfPath, "pdf");
com.spire.xls.Workbook wb = new com.spire.xls.Workbook();
wb.loadFromFile(excelPath);
wb.saveToFile(pdfPath, com.spire.xls.FileFormat.PDF);
} //将html转成pdf
public static void htmlToPdf(String htmlPath, String pdfPath) {
try {
pdfPath = FileUtil.getNewFileFullPath(pdfPath, pdfPath, "pdf");
File file = new File(pdfPath); // 新建一个空白pdf文档
FileOutputStream os = new FileOutputStream(file);
Document doc = new Document(htmlPath); // Address是将要被转化的word文档
doc.save(os, com.aspose.words.SaveFormat.PDF);
} catch (Exception e) {
e.printStackTrace();
}
} //将ppt文件转成pdf
public static void pptToPdf(String pptPath, String pdfPath) throws IOException {
pdfPath = FileUtil.getNewFileFullPath(pptPath, pdfPath, "pdf");
com.itextpdf.text.Document document = null;
FileOutputStream fileOutputStream = null;
PdfWriter pdfWriter = null;
try {
InputStream inputStream = Files.newInputStream(Paths.get(pptPath));
SlideShow<?, ?> slideShow;
String ext = pptPath.substring(pptPath.lastIndexOf("."));
if (ext.equals(".pptx")) {
slideShow = new XMLSlideShow(inputStream);
} else {
slideShow = new HSLFSlideShow(inputStream);
}
Dimension dimension = slideShow.getPageSize();
fileOutputStream = new FileOutputStream(pdfPath);
//document = new com.itextpdf.text.Document();
document = new com.itextpdf.text.Document(new com.itextpdf.text.Rectangle((float) dimension.getWidth(), (float) dimension.getHeight()));
pdfWriter = PdfWriter.getInstance(document, fileOutputStream);
document.open();
for (Slide<?, ?> slide : slideShow.getSlides()) {
// 设置字体, 解决中文乱码
setPPTFont(slide, "宋体");
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 java.awt.Font("宋体", java.awt.Font.PLAIN, 12));
slide.draw(graphics2d);
graphics2d.dispose();
com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance(bufferedImage, null);
image.scaleToFit((float) dimension.getWidth(), (float) dimension.getHeight());
document.add(image);
document.newPage();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (document != null) {
document.close();
}
if (fileOutputStream != null) {
fileOutputStream.close();
}
if (pdfWriter != null) {
pdfWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
} private static void setPPTFont(Slide<?, ?> slide, String fontFamily) {
// 设置字体, 解决中文乱码
for (Shape<?, ?> shape : slide.getShapes()) {
if (shape instanceof TextShape) {
TextShape textShape = (TextShape) shape;
List<TextParagraph> textParagraphs = textShape.getTextParagraphs();
for (TextParagraph textParagraph : textParagraphs) {
List<TextRun> textRuns = textParagraph.getTextRuns();
for (TextRun textRun : textRuns) {
textRun.setFontFamily(fontFamily);
}
}
}
}
}
}

文档在线预览(四)将word、txt、ppt、excel、图片转成pdf来实现在线预览的更多相关文章

  1. C# 将Word,Execl,PPT,Project, 文件转成PDF, 不依赖Office!!

    git 地址 https://gitee.com/bandung/Execl_WordTOPDF.git 包括了各种破解的dll Word转PDF 挨个引用 Word转PDF public void ...

  2. PDF文档转换为图片、图片转成PDF 及PDF合并

    简介 功能:PDF文档按每页转换成一张图片,一张图片转换成一张PDF 并将多张PDF合成一个多页的PDF文档. 经历:在各个网站上搜索始终出现各种问题,尤其是遇到引用的版本问题尤其头疼,不是不能适用当 ...

  3. Java操作word文档使用JACOB和POI操作word,Excel,PPT需要的jar包

    可参考文档: http://wibiline.iteye.com/blog/1725492 下载jar包 http://download.csdn.net/download/javashixiaofe ...

  4. C#服务器端生成报告文档:使用帆软报表生成Word、Pdf报告

    一.帆软报表简介 报表工具中,帆软报表相比Crystal Report(水晶报表).SQL Server Report Service(SSRS)等报表工具来说算是佼佼者,此外帆软报表在统计图表.数据 ...

  5. Android根据word模板文档将表单数据生成word文档的方案整理

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 尝试的方案包括以下几种: freemarker 只能在java项目上运行,无法在Android项目上运行: 参考资料:<Fre ...

  6. 文档大师 在Win10 IE11下,文档集画面无法正常显示Word等Office文档的解决方法

    在文档集界面中显示Word文档,是文档大师的一个核心功能. 最近在 Win10 升级到最新版后,发现 无法正常显示Office 文档的问题. 一开始以为是Word版本问题,从2007升级到2016,问 ...

  7. 阅读MDN文档之布局(四)

    Introducing positioning Static positioning Relative positioning Introducing top, bottom, left and ri ...

  8. React文档(二十四)高阶组件

    高阶组件(HOC)是React里的高级技术为了应对重用组件的逻辑.HOCs本质上不是React API的一部分.它是从React的组合性质中显露出来的模式. 具体来说,一个高阶组件就是一个获取一个组件 ...

  9. 用python从符合一定格式的txt文档中逐行读取数据并按一定规则写入excel(openpyxl支持Excel 2007 .xlsx格式)

    前几天接到一个任务,从gerrit上通过ssh命令获取一些commit相关的数据到文本文档中,随后将这些数据存入Excel中.数据格式如下图所示 观察上图可知,存在文本文档中的数据符合一定的格式,通过 ...

  10. NPOI 2.1.1 系列(1) 使用NPOI读取 Excel文档 ;NpoiExcelHelper 导入导出 2003格式 2007格式的 Excel; Npoi 导出 xlsx 格式

    下载地址 http://npoi.codeplex.com/releases 下面放一个 NPOIHelper 助手类吧,也不是我写的- NpoiExcelHelper 可以生成xlsx格式publi ...

随机推荐

  1. 团队如何选择合适的Git分支策略?

    现代软件开发过程中要实现高效的团队协作,需要使用代码分支管理工具实现代码的共享.追溯.回滚及维护等功能.目前流行的代码管理工具,包括CVS,SVN,Git,Mercurial等. 相比CVS和SVN的 ...

  2. ChatGPT 通识入门

    最近网络上对于Chat GPT的讨论热潮不断地膨胀,一个势必给整个人类社会带来新变革的科技和工具产生了.这个新的工具能够识别自然语言并能够理解上下文的语境,并能够具备人类思维的模型. 但是ChatGP ...

  3. 关于关键字extends与implements的不同以及关于接口的详细介绍的文章

    extends与implements的不同 1.在类的声明中,通过关键字extends来创建一个类的子类. 一个类通过关键字implements声明自己使用一个或者多个接口. extends 是继承某 ...

  4. sync.Pool:提高Go语言程序性能的关键一步

    1. 简介 本文将介绍 Go 语言中的 sync.Pool并发原语,包括sync.Pool的基本使用方法.使用注意事项等的内容.能够更好得使用sync.Pool来减少对象的重复创建,最大限度实现对象的 ...

  5. Java设计模式 —— 装饰模式

    12 装饰模式 12.1 装饰模式概述 Decorator Pattern: 动态地给一个对象增加一些额外的职责.提供一种比使用子类更加灵活的方案来扩展功能. 装饰模式是一种用于替代继承的技术,通过一 ...

  6. 论文解析 -- A Survey of AIOps Methods for Failure Management

    此篇Survey是A Systematic Mapping Study in AIOps的后续研究 对于AIOPS中占比较高的Failure Management进行进一步的研究 Compared t ...

  7. MySQL大量脏数据,如何只保留最新的一条?

    因为系统的一个Bug,导致数据库表中出现重复数据,需要做的是删除重复数据且只保留最新的一条数据. 具体场景是这样的 有张订单关联额外费用表,而且一个订单号(order_no)记录只能关联同一个费用(c ...

  8. 2023-04-20:有一堆石头,用整数数组 stones 表示 其中 stones[i] 表示第 i 块石头的重量。 每一回合,从中选出任意两块石头,然后将它们一起粉碎 假设石头的重量分别为 x 和

    2023-04-20:有一堆石头,用整数数组 stones 表示 其中 stones[i] 表示第 i 块石头的重量. 每一回合,从中选出任意两块石头,然后将它们一起粉碎 假设石头的重量分别为 x 和 ...

  9. 第3章. markdown语法

    常用语法 1. 文字格式 1.1 给文字添加引用 在文字的两侧,使用 ` 符号包裹起来 怒发冲冠,凭栏处,潇潇雨歇. 1.2 设置文字样式为斜体 在文字的两侧,使用 * 符号包裹起来 抬望眼,仰天长啸 ...

  10. Python 函数及参数的使用

    函数 带名字的代码块,用于完成具体的工作 关键字def定义一个函数,定义函数名,括号内是需要完成任务所需要的信息,最后定义冒号结尾 缩进构成函数体 函数调用,依次指定函数名以及冒号括起来的必要信息 d ...