背景
在某些场景下,我们需要将 PDF 文件的内容转换为图片,然后将图片返回给前端进行展示,比如下面情况:
红色方框所示区域为图片,所以进行PDF 转图片的操作就有必要了。
实现思路
- 对文件扩展名进行校验
- 读取PDF文件内容
- 将文件内容渲染为BufferedImage对象
- 保存图片文件
具体代码
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import static com.xjl.common.constant.EscapeCharacterEnum.ESCAPE_CHARACTER_WINDOWS_O_LINUX;
import static com.xjl.common.constant.ExtensionConstant.PPDF;
import static com.xjl.common.constant.ExtensionConstant.PPNG;
/**
* PDF转图片工具类
*
* @author b16mt
*/
public class PdfToImageUtil {
/**
* 图片保存性能
* 高性能:BINARY,损失清晰度,获得转换速度与存储空间
* 中性能:GRAY,平衡决定,在转换速度与存储空间里得到新的体验
* 低性能:RGB,损失转换速度与存储空间,获得更好地可视程度和清晰度
*/
private static final ImageType IMAGE_SAVING_PERFORMANCE_LOWER = ImageType.RGB;
private static final ImageType IMAGE_SAVING_PERFORMANCE_MIDDLE = ImageType.GRAY;
private static final ImageType IMAGE_SAVING_PERFORMANCE_SENIOR = ImageType.BINARY;
/**
* 图片保存精度
* 高精度:300dpi,存储的图像会消耗过高的存储空间和转换时间
* 中精度:150~200dpi,推荐方案,平衡决定
* 低精度:100dpi,存储的图像会相对模糊
*/
private static final int IMAGE_SAVING_DEFINITION_LOWER = 100;
private static final int IMAGE_SAVING_DEFINITION_MIDDLE = 150;
private static final int IMAGE_SAVING_DEFINITION_SENIOR = 300;
/**
* 执行后续操作前的校验
*
* @param imgInputPath 包含要处理的PDF文件的目录路径
* @param imgOutputPath 保存生成图像的目录路径
*/
public static String oneVerificationExecution(String imgInputPath, String imgOutputPath) {
// 创建输入和输出目录的File对象
File inputFolder = new File(imgInputPath);
// 仅处理PDF文件(文件扩展名以“.pdf”结尾)
if (inputFolder.isFile() && inputFolder.getName().toLowerCase().endsWith(PPDF)) {
// 调用convertPdfToImages方法,将PDF文件转换为图像
return convertPdfToImages(inputFolder, imgOutputPath);
}
return null;
}
/**
* 将PDF文件转换为一系列图像
*
* @param pdfFile 要转换为图像的输入PDF文件
* @param savePath 生成图像的保存目录
*/
private static String convertPdfToImages(File pdfFile, String savePath) {
// 从提供的文件加载PDF文档
try (PDDocument document = PDDocument.load(pdfFile)){
// 为文档创建PDFRenderer以渲染页面
PDFRenderer pdfRenderer = new PDFRenderer(document);
// 以150 DPI和 GRAY 图像类型呈现页面为 BufferedImage
BufferedImage bufferedImage = pdfRenderer.renderImageWithDPI(0, IMAGE_SAVING_DEFINITION_SENIOR, IMAGE_SAVING_PERFORMANCE_MIDDLE);
// 生成全局唯一文件名
// 可以使用uuid
SnowflakeFileGeneratorUtil generator = new SnowflakeFileGeneratorUtil(1, 1);
// 为当前页面的图像生成唯一的输出文件名
String outputFileName = "image_" + generator.generateUniqueId() + PPNG;
File outputFile = new File(savePath, outputFileName);
// 将呈现的图像保存为PNG文件
ImageIO.write(bufferedImage, "PNG", outputFile);
return savePath + ESCAPE_CHARACTER_WINDOWS_O_LINUX.getSymbol() + outputFileName;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
解释
校验PDF文件是否合法(主要判断是否为pdf扩展名的文件),这里可以自己去自定义其他校验规则
/**
* 执行后续操作前的校验
*
* @param imgInputPath 包含要处理的PDF文件的目录路径
* @param imgOutputPath 保存生成图像的目录路径
*/
public static String oneVerificationExecution(String imgInputPath, String imgOutputPath) {
// 创建输入和输出目录的File对象
File inputFolder = new File(imgInputPath);
// 仅处理PDF文件(文件扩展名以“.pdf”结尾)
if (inputFolder.isFile() && inputFolder.getName().toLowerCase().endsWith(PPDF)) {
// 调用convertPdfToImages方法,将PDF文件转换为图像
return convertPdfToImages(inputFolder, imgOutputPath);
}
return null;
}
读取PDF文件内容,使用try...catch包围确保资源释放
// 从提供的文件加载PDF文档
try (PDDocument document = PDDocument.load(pdfFile)){
// 为文档创建PDFRenderer以渲染页面
PDFRenderer pdfRenderer = new PDFRenderer(document);
...
...
} catch (Exception e) {
e.printStackTrace();
}
将文件内容渲染为BufferedImage对象,可以根据具体业务需求选择不同性能、精度的图片:
- 高性能:IMAGE_SAVING_PERFORMANCE_LOWER,损失清晰度,获得转换速度与存储空间
- 中性能:IMAGE_SAVING_PERFORMANCE_MIDDLE,平衡决定,在转换速度与存储空间里得到新的体验
- 低性能:IMAGE_SAVING_PERFORMANCE_SENIOR,损失转换速度与存储空间,获得更好地可视程度和清晰度
- 高精度:IMAGE_SAVING_DEFINITION_LOWER,存储的图像会消耗过高的存储空间和转换时间
- 中精度:IMAGE_SAVING_DEFINITION_MIDDLE,推荐方案,平衡决定
- 低精度:IMAGE_SAVING_DEFINITION_SENIOR,存储的图像会相对模糊
性能越高 + 精度越低转换的速度就会越快,反之就会越慢
// 以150 DPI和 GRAY 图像类型呈现页面为 BufferedImage
BufferedImage bufferedImage = pdfRenderer.renderImageWithDPI(0, IMAGE_SAVING_DEFINITION_SENIOR, IMAGE_SAVING_PERFORMANCE_MIDDLE);
输出图片,推荐png格式,当然也可以自己自定义其他格式
// 将呈现的图像保存为PNG文件
ImageIO.write(bufferedImage, "PNG", outputFile);
一行代码调用
两个参数:
- pdfInputPath pdf输入路径
- imgSavePath 图片保存路径
oneVerificationExecution(pdfInputPath, imgSavePath);
可以使用String接收返回值,返回值为文件存储路径(文件是本地化存储)