使用forkJoinPool框架将PDF文件分页转成PNG图片

 

forkJoinPool框架概述和注意事项可参考:     http://ifeve.com/fork-join-1/

 

@SofaReference
    private OssClientService ossClientService;

    /***
     * PDF文件转PNG图片,全部页数,使用forkJoinPool
     *
     * @param pdfOssKey pdf文件ossKey
     * @param dpi dpi越大转换后越清晰,相对转换速度越慢,例如:300
     * @return
     */
    @Override
    public List<byte[]> pdfToPng(String pdfOssKey, int dpi) {
        Stopwatch stopwatch = Stopwatch.createStarted();
        PDDocument pdDocument = null;
        InputStream inputStream = null;
        List<byte[]> imageByteArrayList = new LinkedList<>();
        try {
            inputStream = ossClientService.getFileInputStream(pdfOssKey);
            pdDocument = PDDocument.load(inputStream);
            PDFRenderer renderer = new PDFRenderer(pdDocument);
            int totalPage = pdDocument.getNumberOfPages();
            if (totalPage <= 0) {
                return imageByteArrayList;
            }
            PdfToPngTask task = new PdfToPngTask(1, totalPage, dpi, renderer);
            ForkJoinPool pool = new ForkJoinPool();
            ForkJoinTask<List<byte[]>> submitResult = pool.submit(task);
            imageByteArrayList = submitResult.get();
            pool.shutdown();
            stopwatch.stop();
            log.info("PDF文档转PNG图片成功!耗时: " + (stopwatch.elapsed(TimeUnit.MILLISECONDS)) + "毫秒");
            return imageByteArrayList;
        } catch (Exception e) {
            log.error("PDF分页转图片发生异常,e={}", e);
            throw new RuntimeException("PDF分页转图片发生异常");
        } finally {
            IOUtils.closeQuietly(pdDocument);
            IOUtils.closeQuietly(inputStream);
        }
    }

    /**
     * 使用ForkJoinPool多线程执行PDF转图片,提高速度
     */
    public  class PdfToPngTask extends RecursiveTask<List<byte[]>> {
        /**
         * 每次执行的页数
         */
        private static final int         THRESHOLD = 2;
        /**
         * 开始页
         */
        private             int         startPage;
        /**
         * 结束页
         */
        private             int         endPage;
        private             int         dpi;
        private             PDFRenderer renderer;

        public PdfToPngTask(int startPage, int endPage, int dpi, PDFRenderer renderer) {
            this.startPage = startPage;
            this.endPage = endPage;
            this.dpi = dpi;
            this.renderer = renderer;
        }

        @Override
        protected List<byte[]> compute() {
            List<byte[]> imageByteArrayList = new LinkedList<>();
            log.info("PDF转图片: startPage={},endPage={}", startPage, endPage);
            boolean canCompute = (endPage - startPage) < THRESHOLD;
            if (canCompute) {
                for (int pageIndex = startPage; pageIndex <= endPage; pageIndex++) {
                    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                    try {
                        BufferedImage image = renderer.renderImageWithDPI(pageIndex - 1, dpi);
                        ImageIO.write(image, "png", byteArrayOutputStream);
                        byte[] imageByteArray = byteArrayOutputStream.toByteArray();
                        imageByteArrayList.add(imageByteArray);
                    } catch (Exception e) {
                        log.error("使用ForkJoin线程池执行PDF转图片过程中发生异常,pageIndex={},e={}", pageIndex, e);
                    } finally {
                        IOUtils.closeQuietly(byteArrayOutputStream);
                    }
                }
            } else {
                int middlPage = (startPage + endPage) / 2;
                PdfToPngTask leftTask = new PdfToPngTask(startPage, middlPage, dpi, renderer);
                PdfToPngTask rightTask = new PdfToPngTask(middlPage + 1, endPage, dpi, renderer);
                invokeAll(leftTask, rightTask);
                imageByteArrayList.addAll(leftTask.join());
                imageByteArrayList.addAll(rightTask.join());
            }
            return imageByteArrayList;
        }
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值