前言:图片转pdf的过程中,能不用**ImageIO.read()**方法就不用,这个方法读取图片会耗费大量时间,转pdf的时间尽量控制在1秒之内
提醒: 传进来的参数不一定要MultipartFile, 读取本地图片或者url(慢点)也可以达到这个速度,注释里有写读取本地图片或url方法的方法
读取url第一种方法:
org.apache.commons.io.FileUtils.toFile()
1. 导入依赖
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>fontbox</artifactId>
<version>2.0.12</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.12</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.5</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
2. pdfbox方式
2.1. 图片转pdf
这里不一定要MultipartFile,就算是本地图片也可以PDImageXObject.createFromFile(imagePath, document);支持本地图片的读取
public static byte[] getPdfBytes(MultipartFile[] imagesFiles) throws IOException {
PDDocument document = new PDDocument();
for (MultipartFile datum : imagesFiles) {
String filename = datum.getOriginalFilename();
String fileSuffix = filename.substring(filename.lastIndexOf(".") + 1);
Iterator readers = ImageIO.getImageReadersByFormatName(fileSuffix);
ImageReader reader = (ImageReader) readers.next();
ImageInputStream input = ImageIO.createImageInputStream(datum.getInputStream());
reader.setInput(input, true);
int width = reader.getWidth(0);
int height = reader.getHeight(0);
PDPage pdPage = new PDPage(new PDRectangle(width, height));
document.addPage(pdPage);
PDImageXObject pdImageXObject = PDImageXObject.createFromByteArray(document, datum.getBytes(), "构建图片错误");
//如果没有文件的字节数组,也可以用下面这个
//String imagePath = "/test";
//PDImageXObject pdImageXObject = PDImageXObject.createFromFile(imagePath, document);
//如果只有url,可以用hutool包的HttpUtil方法下载下来,得到的结果是字节数组,不过会耗时长
PDPageContentStream contentStream = new PDPageContentStream(document, pdPage);
//写入图片
contentStream.drawImage(pdImageXObject, 0, 0);
contentStream.close();
}
ByteArrayOutputStream output = new ByteArrayOutputStream();
document.save(output);
document.close();
return output.toByteArray();
}
2.2. pdf+ 图片转pdf
很简单直接将上面的PDDocument document = new PDDocument();
换成
//读取上传pdf文件
PDDocument document = PDDocument.load(pdfFile.getInputStream()); //pdfFile也是MultipartFile,这里直接用需要读取pdf文件流就可以了
下面的代码和上面的方法一样
2.3. pdf转图片
/**
* @ Author :chl
* @ Date :Created in 14:40 2023/3/1
* @ Description:可以改成返回值为List<byte[]>
* @param imageFolderPath 存放图片文件路径
* @param pdfSourcePath 需要读取的pdf路径
* @param dpi 这个越大,图片越清晰,300挺清楚了
* @param formatName
* @ return void
*/
public static void loadPdf2Image(String imageFolderPath, String pdfSourcePath, int dpi, String formatName) throws Exception {
PDDocument document = PDDocument.load(new File(pdfSourcePath));
PDFRenderer renderer = new PDFRenderer(document);
for (int i = 0; i < document.getNumberOfPages(); i++) {
BufferedImage bufferedImage = renderer.renderImageWithDPI(i, dpi);
String imagePath = imageFolderPath + i + "." + formatName;
FileOutputStream fileOutputStream = new FileOutputStream(imagePath);
ImageIO.write(bufferedImage, formatName, fileOutputStream);
}
document.close();
}
3、itext 方式
3.1. 图片转pdf
/**
* @ Author :chl
* @ Date :Created in 11:08 2023/3/2
* @ Description:性能翻倍
* @param data
* @ return byte[]
*/
public static byte[] multipartFile2pdf2(MultipartFile[] data) {
Document document = new Document();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
PdfWriter.getInstance(document, bos);
document.open();
for (MultipartFile datum : data) {
Image image = null;
ImageInputStream input = null;
int width = 0;
int height = 0;
try {
String filename = datum.getOriginalFilename();
String fileSuffix = filename.substring(filename.lastIndexOf(".") + 1);
Iterator readers = ImageIO.getImageReadersByFormatName(fileSuffix);
ImageReader reader = (ImageReader) readers.next();
input = ImageIO.createImageInputStream(datum.getInputStream());
reader.setInput(input, true);
width = reader.getWidth(0);
height = reader.getHeight(0);
//加载图片
image = Image.getInstance(datum.getBytes());
//如果不能直接得到图片字节数组,可以直接,不用再用FileOutputStream读了
//image = Image.getInstance(filePath);
//居中
image.setAlignment(Image.MIDDLE);
} catch (BaseException e) {
throw new BaseException("加载上传图片错误");
}
//页面大小是图片大小, 和newPage位置不能对调,否则生成烂图
document.setPageSize(new Rectangle(width, height));
document.newPage();
document.add(image);
input.close();
}
document.close();
} catch (BaseException be) {
throw new BaseException("加载上传图片错误");
} catch (Exception e) {
e.printStackTrace();
}
return bos.toByteArray();
}
3.2. 图片+pdf 转成pdf
public static byte[] pdfAndImage2Pdf(MultipartFile pdfFile, MultipartFile[] imagesFiles) throws IOException {
PdfReader pdfReader = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
PdfStamper pdfStamper = null;
try {
//load pdf
pdfReader = new PdfReader(pdfFile.getBytes());
//打开pdf编辑器
pdfStamper = new PdfStamper(pdfReader, bos);
for (MultipartFile datum : imagesFiles) {
String filename = datum.getOriginalFilename();
String fileSuffix = filename.substring(filename.lastIndexOf(".") + 1);
Iterator readers = ImageIO.getImageReadersByFormatName(fileSuffix);
ImageReader reader = (ImageReader) readers.next();
ImageInputStream input = ImageIO.createImageInputStream(datum.getInputStream());
reader.setInput(input, true);
int width = reader.getWidth(0);
int height = reader.getHeight(0);
Image image = Image.getInstance(datum.getBytes());
image.setAlignment(Image.MIDDLE);
//添加空白页
pdfStamper.insertPage(pdfReader.getNumberOfPages() + 1, new Rectangle(width, height));
//捕获空白页
PdfContentByte overContent = pdfStamper.getOverContent(pdfReader.getNumberOfPages());
image.scaleAbsolute(width, height);
//设置绝对位置
image.setAbsolutePosition(0, 0);
overContent.addImage(image);
input.close();
}
}catch (Exception e) {
e.printStackTrace();
} finally {
try {
pdfStamper.close();
pdfReader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return bos.toByteArray();
}