PdfUtil

import org.apache.pdfbox.io.MemoryUsageSetting;

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.font.PDFont;

import org.apache.pdfbox.pdmodel.font.PDType1Font;

import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;

import org.apache.pdfbox.rendering.PDFRenderer;

import org.apache.pdfbox.util.Matrix;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;



import javax.imageio.ImageIO;

import java.awt.image.BufferedImage;

import java.io.*;

import java.util.Base64;

import java.util.List;



public class PdfUtil {

    private static final Logger LOG = LoggerFactory.getLogger(PdfUtil.class);



    private static final String PRE_HTML_CODE = "<html><head><meta charset=\"UTF-8\"></head>" +

            "<body style=\"background-color:gray;\"><style>" +

            "img {background-color:#fff; text-align:center; " +

            "width:100%; max-width:100%;margin-top:6px;}</style>";



    private static final String SUF_HTML_CODE = "</body></html>";

    private static final String MID_HTML_CODE = "<img src=\"data:image/png;base64,";

    private static final String MIDD_HTML_CODE = "\">";



    /**

     * pdf转html

     */

    public static String pdfToHtml(InputStream inputStream) {

        StringBuilder sb = new StringBuilder();

        sb.append(PRE_HTML_CODE);

        PDDocument document = null;

        ByteArrayOutputStream outputStream = null;

        try {

            document = PDDocument.load(inputStream);

            int pages = document.getNumberOfPages();

            PDFRenderer render = new PDFRenderer(document);



            BufferedImage image;

            for (int i = 0; i < pages; i++) {

                sb.append(MID_HTML_CODE);



                outputStream = new ByteArrayOutputStream();

                image = render.renderImage(i, 2.5f);

                ImageIO.write(image, "png", outputStream);



                sb.append(Base64.getEncoder().encodeToString(outputStream.toByteArray()));

                sb.append(MIDD_HTML_CODE);

            }

        } catch (IOException e) {

            LOG.error(e.getMessage());

        } finally {

            if (null != outputStream) {

                try {

                    outputStream.close();

                } catch (IOException ex) {

                }

            }

            if (null != document) {

                try {

                    document.close();

                } catch (IOException ex) {

                }

            }

        }

        sb.append(SUF_HTML_CODE);



        return sb.toString();

    }



    /**

     * pdf合并

     *

     * @param inputStreams 输入流

     * @param outputStream 输出流

     */

    public static void mergePdf(List<InputStream> inputStreams, OutputStream outputStream) {

        try {

            PDFMergerUtility pdfMergerUtility = new PDFMergerUtility();

            inputStreams.forEach(pdfMergerUtility::addSource);

            pdfMergerUtility.setDestinationStream(outputStream);



            pdfMergerUtility.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly());

        } catch (Exception e) {

            throw new RuntimeException("pdf合并失败: " + e.getMessage(), e);

        }

    }



    private static final PDFont DEFAULT_FONT = PDType1Font.TIMES_BOLD;

    private static final Float FONT_SIZE = 20.0f;

    private static final int OFFSET_X = 20;

    private static final int OFFSET_Y = 20;



    /**

     * pdf header中增加自定义文字

     *

     * @param inputStream  输入流

     * @param outputStream 输出流

     */

    public static void appendHeaderText(InputStream inputStream, OutputStream outputStream, String appendText) {

        try {

            PDDocument doc = PDDocument.load(inputStream);

            doc.setAllSecurityToBeRemoved(true);

            for (PDPage page : doc.getPages()) {

                PDPageContentStream cs = new PDPageContentStream(doc, page, PDPageContentStream.AppendMode.APPEND, true, true);

                PDRectangle pdRectangle = page.getBBox();



                cs.beginText();

                cs.setFont(DEFAULT_FONT, FONT_SIZE);

                // 文字位置,指定x轴、y轴坐标偏移量

                Matrix matrix = Matrix.getTranslateInstance(pdRectangle.getLowerLeftX() + OFFSET_X, pdRectangle.getUpperRightY() - OFFSET_Y);

                cs.setTextMatrix(matrix);

                cs.showText(appendText);

                cs.endText();

                try {

                    cs.close();

                } catch (Exception e) {



                }

            }

            doc.save(outputStream);

        } catch (Exception e) {

            throw new RuntimeException("新增内容失败", e);

        }

    }



    /**

     * 根据图片创建pdf对象

     *

     * @param inputStream  输入流

     * @param outputStream 输出流

     */

    public static void createPDFFromImage(InputStream inputStream, OutputStream outputStream) {

        try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {

            byte[] cached = new byte[1024];

            int read;

            while ((read = inputStream.read(cached)) > -1) {

                byteArrayOutputStream.write(cached, 0, read);

            }



            createPDFFromImage(byteArrayOutputStream.toByteArray(), outputStream);

        } catch (Exception e) {

            throw new RuntimeException("图片生成pdf失败", e);

        }

    }



    /**

     * 根据文件内容获取对应pdf对象

     *

     * @param imageContent 图片内容

     * @param outputStream 输出流

     */

    private static void createPDFFromImage(byte[] imageContent, OutputStream outputStream) {

        try (PDDocument doc = new PDDocument()) {

            PDPage page = new PDPage();

            doc.addPage(page);



            // 获取图片大小

            PDImageXObject ximage = PDImageXObject.createFromByteArray(doc, imageContent, "");

            // 图片宽度

            int imageWidth = ximage.getWidth();

            // 图片高度

            int imageHeight = ximage.getHeight();



            // 获取pdf page大小

            PDRectangle pdRectangle = page.getBBox();

            float pageWidth = pdRectangle.getUpperRightX();

            // pdf高度需要预留增加文本部分

            float pageHeight = pdRectangle.getUpperRightY() - OFFSET_Y;



            // 分别计算宽度和高度的缩放量,并取缩放量中更小值所谓实际缩放量

            float widthScale = pageWidth / imageWidth;

            float heightScale = pageHeight / imageHeight;

            float realScale = widthScale < heightScale ? widthScale : heightScale;



            // 计算实际宽度

            float realWidth = ximage.getWidth() * realScale;

            float realHeight = ximage.getHeight() * realScale;



            try (PDPageContentStream contentStream = new PDPageContentStream(doc, page,

                    PDPageContentStream.AppendMode.OVERWRITE, true, true)) {

                // x轴偏移量为page宽度 - 真实宽度的二分之一

                // y轴偏移量为page高度 - 真实高度的二分之一

                contentStream.drawImage(ximage, (pageWidth - realWidth) / 2, (pageHeight - realHeight) / 2, realWidth, realHeight);

            }

            doc.save(outputStream);

        } catch (Exception e) {

            throw new RuntimeException("Image转图片失败", e);

        }



    }

}

 

posted @ 2020-09-10 13:32  发丝有些凌乱丶  阅读(537)  评论(0编辑  收藏  举报