@

之前在写文档在线预览时留下了一个小坑,当时比较推荐的做法是将各种类型的文档都由后端统一转成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. 用python的pylab画wave波形之sampwidth问题

    问题 网上找了好多地方,核心代码都是一样的,比如这句. wavedata=np.fromstring(bindata,dtype=np.short) 效果也还行. 可一次随机加载了一个Office里的 ...

  2. rocketmq-spring : 实战与源码解析一网打尽

    RocketMQ 是大家耳熟能详的消息队列,开源项目 rocketmq-spring 可以帮助开发者在 Spring Boot 项目中快速整合 RocketMQ. 这篇文章会介绍 Spring Boo ...

  3. 3d基础 - 从模型坐标到屏幕坐标

    在 3D 引擎中,场景通常被描述为三维空间中的模型或对象,每个模型对象由许多三维顶点组成.最终,这些模型对象将在平面屏幕上呈现和显示. 渲染场景始终相对于摄像机,因此,还必须相对于摄像机的视图定义场景 ...

  4. hdfs集群的扩容和缩容

    目录 1.背景 2.集群黑白名单 3.准备一台新的机器并配置好hadoop环境 3.1 我们现有的集群规划 3.2 准备一台新的机器 3.2.1 查看新机器的ip 3.2.2 修改主机名和host映射 ...

  5. 生产事故-记一次特殊的OOM排查

    入职多年,面对生产环境,尽管都是小心翼翼,慎之又慎,还是难免捅出篓子.轻则满头大汗,面红耳赤.重则系统停摆,损失资金.每一个生产事故的背后,都是宝贵的经验和教训,都是项目成员的血泪史.为了更好地防范和 ...

  6. 补五月四号java基础知识

    1.在JDK5中新增了自动包装和自动解包功能:当编译器发现程序再应该使用包装类对象的地方却使用基本数据类型的数据时,编译器将自动把该数据包装为该基本数据对应的包装类的对象,这个过程成为自动包装.如类型 ...

  7. Windows 本地安装mysql8.0

    前言 看了网上许多关于Windows 本地安装mysql的很多教程,基本上大同小异.但是安装软件有时就可能因为一个细节安装失败.我也是综合了很多个教程才安装好的,所以本教程可能也不是普遍适合的.现我将 ...

  8. 电脑上跨平台的电子书阅读器Koodo Reader

    https://wbsu2003.gitee.io/2021/04/30/%E7%94%B5%E8%84%91%E4%B8%8A%E8%B7%A8%E5%B9%B3%E5%8F%B0%E7%9A%84 ...

  9. 虚拟内存与malloc/new原理详解

    malloc malloc()函数并不是系统调用,而是 C 库里的函数,用于动态分配内存.malloc() 分配的是虚拟内存,而不是物理内存.如果分配后的虚拟内存没有被访问的话,是不会将虚拟内存映射到 ...

  10. 如何玩转国产神器:接口一体化协作平台Apifox!

    前言:Apifox是什么? 简介: 简单来说,Apifox = swagger + mock + postman+Jmeter,是API 文档.API 调试.API Mock.API 自动化测试一体化 ...