@
程式碼基於 aspose-words(用於word、txt轉pdf),itextpdf(用於ppt、圖片、excel轉pdf),所以事先需要在專案裡下面以下依賴
<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>
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的方法比較簡單,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檔案程式碼直接複用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,那就讓我們把ppt轉成pdf再用吧。其實從這裡開始程式碼就開始複雜起來了,這裡用到了Apache poi、itextpdf、Graphics2D三個庫,於是我結合這三個庫同時相容ppt、pptx寫出了第一版程式碼
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離去,於是我根據這個改了改程式碼寫出了第二版程式碼
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()));
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用到了用到了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一樣無法解析
話不多說我們先結合Apache poi、itextpdf兩個庫簡單協定版基本的圖片轉換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大小,所以在圖片過大時會顯示不完整,所以我們在圖片過大時需要對圖片進行一些調整,調整後的程式碼如下:
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程式碼:
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在實際的應用場景中應該比較罕見,但是前面也說了這麼多檔案轉pdf的方式了,那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();
}
}
驗證程式碼:
public static void main(String[] args) throws Exception {
excelToPdf("C:\\Users\\jie\\Desktop\\新建 Microsoft Excel 工作表.xlsx", "D:\\test");
}
轉換效果如下
因為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);
}
}
}
}
}
}