Java实现PDF转图片

1.场景

最近一直在跟一个项目,遇到了一个之前没做过的需求:运营在后台上传pdf文件,在官网的前台展示图片文件。之所以展示图片文件是因为在官网前台展示的是一个弹窗,要直接弹出pdf会比弹出图片的难度大一些。

2.解决方案

在搜罗了一些解决方案之后,最终敲定是使用“pdfbox”,当然相对应的还有一些其他的解决方案,大家可以酌情参考。pdfbox是比较适合我们所需的业务场景的,下面我来介绍一下实现步骤:

3.实现步骤

1.依赖引入
compile ('org.apache.pdfbox:pdfbox:2.0.9')
2.实现原理
  1. 获取到相应的PDF对象,对PDF按页进行遍历
  2. 对遍历得到的每一页PDF进行图片转换
  3. 把生成的图片存储到相应的文件夹中
  4. 加入相应的重试策略
3.实现代码

Pdf2PictureUtils:

public class Pdf2PictureUtils {

    private Pdf2PictureUtils() {
    }

    //图片最大  临时写死 后续从redis+db取
    private static final int MAXSIZE = 600;

    private static final int SIZE = 10;

    private static int MAX_DPI = 80;

    /**
     * pdfFile和targetPath 不能在同一路径下,否则不能生成图片
     *
     * @param pdfFile
     * @param targetPath
     * @return com.huajin.guofubank.business.po.PdfPicInfo
     * @author ss.xin
     * @date 2021/7/12 16:26
     */
    public static PdfPicInfo cutPDFToJPGByPdfBox(String pdfFile, String targetPath) {
        PdfPicInfo result = new PdfPicInfo();
        File pdf = new File(pdfFile);
        if (!pdf.exists() || !pdf.isFile()) {
            return result;
        }
        File target = new File(targetPath);
        boolean generated = target.exists() && target.isDirectory() && target.listFiles().length > 0;
        target.mkdirs();
        try (PDDocument doc = PDDocument.load(pdf)) {
            PDFRenderer renderer = new PDFRenderer(doc);
            for (int i = 0; i < doc.getNumberOfPages(); i++) {
                //递归 直到符合要求
                BufferedImage imageOrign = imageToBytes("PNG", renderer, i, MAX_DPI);
                result.setHeight(imageOrign.getHeight());
                result.setWidth(imageOrign.getWidth());
                //如果文件只生成部分,mq重试,后续的也要生成!,失败时的最后一张图片可能有问题,要重新生成
                //若原本需要生成五张图片,实际生成了3张,那就需要把第3,4,5张重新生成
                if (!generated || i > target.listFiles().length - 2) {
                    File file = new File(targetPath + pdf.getName().substring(0, pdf.getName().lastIndexOf('.')) + "_" + i + ".png");
                    if (file.exists()) {
                        file.delete();
                    }
                    ImageIO.write(imageOrign, "PNG", file);
                }
            }
            result.setCount(target.listFiles().length);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 计算图片大小
     * @param format
     * @param renderer
     * @param i
     * @param maxDpi
     * @return java.awt.image.BufferedImage
     * @author ss.xin
     * @date 2021/7/12 16:27
     */
    public static BufferedImage imageToBytes(String format, PDFRenderer renderer, int i, int maxDpi) throws IOException {
        BufferedImage imageOrign = renderer.renderImageWithDPI(i, maxDpi);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            ImageIO.write(imageOrign, format, out);
        } catch (IOException e) {
            return imageOrign;
        } finally {
            if (out != null) {
                out.close();
            }
        }
        byte[] byteArry = out.toByteArray();
        if (byteArry != null && byteArry.length / 1024 < MAXSIZE) {
            return imageOrign;
        }
        maxDpi -= SIZE;
        return imageToBytes(format, renderer, i, maxDpi);
    }

}

PdfPicInfo:

@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public class PdfPicInfo {
	
	int count;
	
	int width;
	
	int height;
	
}
4.注意点

代码中有相应的重试策略,大家可以着重理解一下其中相应的逻辑

有疑问的话,欢迎及时交流~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值