java pdf工具类,pdf转图片,图片转pdf

2020年10月21日 1542点热度 0人点赞 0条评论

前言

在项目中遇到了需要把合同的pdf 展示给用户查看,这时候直接给用户查看 pdf 问题挺多的,首先是加载慢,然后还有安卓,ios等手机兼容问题,有个 pdfjs 组件,但是用起来也是问题挺多的,遂直接换套方案,直接将 pdf 生成的时候同时生成一份 png 图片后面展示给用户看。这里记录下。

方法

maven 导包

        <!-- https://mvnrepository.com/artifact/org.apache.pdfbox/fontbox -->
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>fontbox</artifactId>
            <version>2.0.9</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox -->
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.9</version>
        </dependency>

        <!-- 如果不导入这个包则很多字符转换出来会模糊不清晰 -->
        <dependency>
            <groupId>com.levigo.jbig2</groupId>
            <artifactId>levigo-jbig2-imageio</artifactId>
            <version>2.0</version>
        </dependency>

工具类

import org.apache.pdfbox.multipdf.PDFMergerUtility;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * @Description
 * @Author ChengQichuan
 * @Version V1.0.0
 * @Since 1.0
 * @Date 2020/10/21
 */
public class PdfUtils {


    /**
     * 下载网络的pdf附件转换成图片
     * @param pdfUrl 网络pdf地址
     * @return
     */
    public static MultipartFile pdfToPng(String pdfUrl) throws MalformedURLException {

        //将本地文件转为byte数组
        byte[] bytes = urlTobyte(pdfUrl);
        //转换图片
        BufferedImage bufferedImage = pdfToPng(new ByteArrayInputStream(bytes));

        MultipartFile multipartFile = FileUtil.inputStreamToMultipartFile(UUID.randomUUID().toString() + ".png", bufferedImageToInputStream(bufferedImage));

        return multipartFile;
    }




    /**
     * 远程url文件地址转成byte
     * @param url
     * @return
     * @throws MalformedURLException
     */
    public static byte[] urlTobyte(String url) throws MalformedURLException {
        URL ur = new URL(url);
        BufferedInputStream in = null;
        ByteArrayOutputStream out = null;
        try {
            in = new BufferedInputStream(ur.openStream());
            out = new ByteArrayOutputStream(1024);
            byte[] temp = new byte[1024];
            int size = 0;
            while ((size = in.read(temp)) != -1) {
                out.write(temp, 0, size);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        byte[] content = out.toByteArray();
        return content;
    }






    /**
     * 合并pdf
     * @param byteList
     * @return
     */
    public static ByteArrayOutputStream mergePdf(List<byte[]> byteList){
        // 接收合并后的pdf文件流对象
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        // 创建PDF合并对象
        PDFMergerUtility merger = new PDFMergerUtility();
        for (byte[] byteArr : byteList) {
            // 添加待合并的PDF字节流
            merger.addSource(new ByteArrayInputStream(byteArr));
        }
        // 设定合并后的输出流对象
        merger.setDestinationStream(outputStream);
        try {
            // 合并PDF
            merger.mergeDocuments(null);
        } catch (IOException e) {
        }
        return outputStream;
    }


    /**
     * 使用pdfbox将jpg转成pdf
     *
     * @param jpgStream jpg输入流
     * @param pdfPath   pdf文件存储路径
     * @throws IOException IOException
     */
    public static void jpgToPdf(InputStream jpgStream, String pdfPath) throws IOException {

        PDDocument pdDocument = new PDDocument();
        BufferedImage image = ImageIO.read(jpgStream);

        PDPage pdPage = new PDPage(new PDRectangle(image.getWidth(), image.getHeight()));
        pdDocument.addPage(pdPage);
        PDImageXObject pdImageXObject = LosslessFactory.createFromImage(pdDocument, image);
        PDPageContentStream contentStream = new PDPageContentStream(pdDocument, pdPage);
        contentStream.drawImage(pdImageXObject, 0, 0, image.getWidth(), image.getHeight());
        contentStream.close();
        pdDocument.save(pdfPath);
        pdDocument.close();
    }


    /**
     * 产生缩略图
     * @param source
     * @param targetW
     * @param targetH
     * @return
     */
    private static BufferedImage resize(BufferedImage source, int targetW, int targetH) {
        int type = source.getType();
        BufferedImage target = null;
        double sx = (double) targetW / source.getWidth();
        double sy = (double) targetH / source.getHeight();
        if (sx > sy) {
            sx = sy;
            targetW = (int) (sx * source.getWidth());
        } else {
            sy = sx;
            targetH = (int) (sy * source.getHeight());
        }
        if (type == BufferedImage.TYPE_CUSTOM) {
            ColorModel cm = source.getColorModel();
            WritableRaster raster = cm.createCompatibleWritableRaster(targetW, targetH);
            boolean alphaPremultiplied = cm.isAlphaPremultiplied();
            target = new BufferedImage(cm, raster, alphaPremultiplied, null);
        } else {
            target = new BufferedImage(targetW, targetH, type);
        }
        Graphics2D g = target.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g.drawRenderedImage(source, AffineTransform.getScaleInstance(sx, sy));
        g.dispose();
        return target;
    }

    /**
     * pdf 转 图片
     * @param pdfInputStream
     */
    public static BufferedImage pdfToPng(InputStream pdfInputStream) {
        try {
            PDDocument doc = PDDocument.load(pdfInputStream);
            PDFRenderer renderer = new PDFRenderer(doc);
            int pages = doc.getNumberOfPages();


            //设置最大宽度和总长度
            int maxWidth = 0;
            int sumHeight = 0;
            List<BufferedImage> bufferedImageList = new ArrayList<>();
            //得到 BufferedImage list
            for(int i = 0 ; i < pages; i++){
                BufferedImage imageBuffer = renderer.renderImageWithDPI(i, 150, ImageType.RGB);
//                BufferedImage imageBuffer = renderer.renderImageWithDPI(i, 300, ImageType.RGB);
                int width = imageBuffer.getWidth();
                int height = imageBuffer.getHeight();
                if (width > maxWidth){
                    maxWidth = width;
                }
                sumHeight += height;

                bufferedImageList.add(imageBuffer);
            }

            //pdf分别转图片后合并
            BufferedImage imageNew = new BufferedImage(maxWidth,sumHeight,BufferedImage.TYPE_INT_RGB);
            int nowHeight = 0;
            for (BufferedImage bufferedImage : bufferedImageList) {
                int width = bufferedImage.getWidth();
                int height = bufferedImage.getHeight();

                int[] imageRgbArray = new int[width *  height];
                imageRgbArray = bufferedImage.getRGB(0, 0, width, height, imageRgbArray, 0, width);

                //SEPARATE_DISTANCE 表示两张图片的间隔距离
                imageNew.setRGB(0, nowHeight, width, height, imageRgbArray, 0, width);

                nowHeight += height;
            }



            return imageNew;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

    }


    /**
     * pdf 转 图片 List
     * @param pdfInputStream
     */
    public static List<BufferedImage> pdfToPngList(InputStream pdfInputStream) {
        try {
            PDDocument doc = PDDocument.load(pdfInputStream);
            PDFRenderer renderer = new PDFRenderer(doc);
            int pages = doc.getNumberOfPages();


            //设置最大宽度和总长度
            int maxWidth = 0;
            int sumHeight = 0;
            List<BufferedImage> bufferedImageList = new ArrayList<>();
            //得到 BufferedImage list
            for(int i = 0 ; i < pages; i++){
//                BufferedImage imageBuffer = renderer.renderImage(i);
                BufferedImage imageBuffer = renderer.renderImageWithDPI(i, 300, ImageType.RGB);
                int width = imageBuffer.getWidth();
                int height = imageBuffer.getHeight();
                if (width > maxWidth){
                    maxWidth = width;
                }
                sumHeight += height;

                bufferedImageList.add(imageBuffer);
            }

            return bufferedImageList;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

    }


    /**
     * pdf 转 图片 备份
     * @param pdfInputStream
     */
    public static BufferedImage pdfToPngBak(InputStream pdfInputStream) {
        try {
            PDDocument doc = PDDocument.load(pdfInputStream);
            PDFRenderer renderer = new PDFRenderer(doc);
            int pages = doc.getNumberOfPages();

            //pdf分别转图片后合并
            BufferedImage imageNew = null;
            for(int i = 0 ; i < pages; i++){
                BufferedImage imageBuffer = renderer.renderImageWithDPI(i, 300, ImageType.RGB);
                int width = imageBuffer.getWidth();
                int height = imageBuffer.getHeight();

                if(imageNew == null){
                    imageNew = new BufferedImage(width+10,(height+10)  * pages,BufferedImage.TYPE_INT_RGB);
                }

                int[] imageRgbArray = new int[width *  height];
                imageRgbArray = imageBuffer.getRGB(0, 0, width, height, imageRgbArray, 0, width);

                //SEPARATE_DISTANCE 表示两张图片的间隔距离
                imageNew.setRGB(0, height * i, width, height, imageRgbArray, 0, width);

            }

            return imageNew;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }

    }


    /**
     * 将BufferedImage转换为InputStream
     * @param image
     * @return
     */
    public static InputStream bufferedImageToInputStream(BufferedImage image){
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        try {
            ImageIO.write(image, "png", os);
            InputStream input = new ByteArrayInputStream(os.toByteArray());
            return input;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }





}

浮生一程

读书-行路-悦人-识物