解決的問題
有些時(shí)候我們需要在項(xiàng)目中展示PDF,但是直接在瀏覽器中加入PDF展示的插件,存在兼容性問題,某些瀏覽器顯示效果不理想,所以我們可以將PDF轉(zhuǎn)為圖片,然后已圖片的方式展示,效果很好。
那么怎么將PDF轉(zhuǎn)為圖片呢?有兩種方式:
| 產(chǎn)品 | 特點(diǎn) |
|---|---|
| Apache 的 PDF box | 免費(fèi);速度稍慢一點(diǎn),但可以接受 |
| E-iceblue 的 Spire.PDF for Java | 轉(zhuǎn)換效果很好;速度快;功能強(qiáng)大,支持轉(zhuǎn)多種格式;收費(fèi) |
Spire.PDF for Java 的轉(zhuǎn)換效果很好,但是如果不購(gòu)買,轉(zhuǎn)換過后會(huì)添加一些水印文字
參考鏈接:https://www.cnblogs.com/Yesi/p/11233238.html
PDF Box的使用
<dependency>
<groupId>net.sf.cssbox</groupId>
<artifactId>pdf2dom</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.12</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-tools</artifactId>
<version>2.0.12</version>
</dependency>
多頁(yè)P(yáng)DF生成多張圖片
新建一個(gè) PdfUtil 工具類
public class PdfUtil {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(PdfUtil.class);
/***
* PDF文件轉(zhuǎn)PNG圖片,全部頁(yè)數(shù)
*
* @param pdfFilePath pdf完整路徑
* @param dpi dpi越大轉(zhuǎn)換后越清晰,相對(duì)轉(zhuǎn)換速度越慢
*/
public static void pdf2Image(String pdfFilePath, int dpi) {
File file = new File(pdfFilePath);
PDDocument pdDocument;
try {
String imgPdfPath = file.getParent();
int dot = file.getName().lastIndexOf('.');
// 獲取圖片文件名
String imagePdfName = file.getName().substring(0, dot);
pdDocument = PDDocument.load(file);
PDFRenderer renderer = new PDFRenderer(pdDocument);
/* dpi越大轉(zhuǎn)換后越清晰,相對(duì)轉(zhuǎn)換速度越慢 */
PdfReader reader = new PdfReader(pdfFilePath);
int pages = reader.getNumberOfPages();
StringBuffer imgFilePath;
for (int i = 0; i < pages; i++) {
String imgFilePathPrefix = imgPdfPath + File.separator + imagePdfName;
imgFilePath = new StringBuffer();
imgFilePath.append(imgFilePathPrefix);
imgFilePath.append("_");
imgFilePath.append((i + 1));
imgFilePath.append(".png");
File dstFile = new File(imgFilePath.toString());
BufferedImage image = renderer.renderImageWithDPI(i, dpi);
ImageIO.write(image, "png", dstFile);
}
log.info("PDF文檔轉(zhuǎn)PNG圖片成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
多頁(yè)P(yáng)DF組合成一張圖片
public class PdfUtil {
public static final int DEFAULT_DPI = 150;
/**
* pdf轉(zhuǎn)圖片
* 多頁(yè)P(yáng)DF會(huì)每頁(yè)轉(zhuǎn)換為一張圖片,下面會(huì)有多頁(yè)組合成一頁(yè)的方法
*
* @param pdfFile pdf文件路徑
* @param outPath 圖片輸出路徑
* @param dpi 相當(dāng)于圖片的分辨率,值越大越清晰,但是轉(zhuǎn)換時(shí)間變長(zhǎng)
*/
public static void pdf2multiImage(String pdfFile, String outPath, int dpi) {
if (ObjectUtil.isEmpty(dpi)) {
// 如果沒有設(shè)置DPI,默認(rèn)設(shè)置為150
dpi = DEFAULT_DPI;
}
try (PDDocument pdf = PDDocument.load(new FileInputStream(pdfFile))) {
int actSize = pdf.getNumberOfPages();
List<BufferedImage> picList = Lists.newArrayList();
for (int i = 0; i < actSize; i++) {
BufferedImage image = new PDFRenderer(pdf).renderImageWithDPI(i, dpi, ImageType.RGB);
picList.add(image);
}
// 組合圖片
ImageUtil.yPic(picList, outPath);
} catch (IOException e) {
e.printStackTrace();
}
}
}
新建 ImageUtil 類
public class ImageUtil {
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(ImageUtil.class);
/**
* 將寬度相同的圖片,豎向追加在一起 ##注意:寬度必須相同
*
* @param picList 文件流數(shù)組
* @param outPath 輸出路徑
*/
public static void yPic(List<BufferedImage> picList, String outPath) {// 縱向處理圖片
if (picList == null || picList.size() <= 0) {
log.info("圖片數(shù)組為空!");
return;
}
try {
// 總高度
int height = 0,
// 總寬度
width = 0,
// 臨時(shí)的高度 , 或保存偏移高度
offsetHeight = 0,
// 臨時(shí)的高度,主要保存每個(gè)高度
tmpHeight = 0,
// 圖片的數(shù)量
picNum = picList.size();
// 保存每個(gè)文件的高度
int[] heightArray = new int[picNum];
// 保存圖片流
BufferedImage buffer = null;
// 保存所有的圖片的RGB
List<int[]> imgRgb = new ArrayList<int[]>();
// 保存一張圖片中的RGB數(shù)據(jù)
int[] tmpImgRgb;
for (int i = 0; i < picNum; i++) {
buffer = picList.get(i);
// 圖片高度
heightArray[i] = offsetHeight = buffer.getHeight();
if (i == 0) {
// 圖片寬度
width = buffer.getWidth();
}
// 獲取總高度
height += offsetHeight;
// 從圖片中讀取RGB
tmpImgRgb = new int[width * offsetHeight];
tmpImgRgb = buffer.getRGB(0, 0, width, offsetHeight, tmpImgRgb, 0, width);
imgRgb.add(tmpImgRgb);
}
// 設(shè)置偏移高度為0
offsetHeight = 0;
// 生成新圖片
BufferedImage imageResult = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int i = 0; i < picNum; i++) {
tmpHeight = heightArray[i];
if (i != 0) {
// 計(jì)算偏移高度
offsetHeight += tmpHeight;
}
// 寫入流中
imageResult.setRGB(0, offsetHeight, width, tmpHeight, imgRgb.get(i), 0, width);
}
File outFile = new File(outPath);
// 寫圖片
ImageIO.write(imageResult, "png", outFile);
} catch (Exception e) {
e.printStackTrace();
}
}
}