Java生成指定背景图片的PDF文件并转为图片

Java生成指定背景图片的PDF文件并转为图片

工具类

package org.jeecg.dts.common.util;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
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.PDType0Font;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.jeecg.common.util.ZosUtil;
import org.jeecg.dts.common.constant.BussinessEnum;
import org.jeecg.dts.common.entity.HwProductRegistCert;
import org.springframework.stereotype.Component;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
@Component
@Slf4j
public class Word2PDFUtils {
    /**
     * 生成产品登记证书并上传图片到存储系统
     * @param productInfo 产品信息
     * @param fontPath 字体文件路径
     * @param backgroundImagePath 背景图片路径
     * @return 上传后的图片URL
     * @throws Exception 处理过程中可能出现的异常
     */
    public static String generateCertificateAndUpload(HwProductRegistCert productInfo,
                                                      String fontPath,
                                                      String backgroundImagePath) throws Exception {
        // 临时文件路径
        String tempDir = System.getProperty("java.io.tmpdir");
        String pdfPath = tempDir + File.separator + "product_cert_" + System.currentTimeMillis() + ".pdf";
        String imagePath = tempDir + File.separator + "product_cert_" + System.currentTimeMillis() + ".png";

        try {
            // 1. 生成PDF证书
            generateCertificate(pdfPath, backgroundImagePath, fontPath, productInfo);

            // 2. 将PDF转换为图片
            pdfToImage(pdfPath, imagePath);

            // 3. 上传图片到存储
            File imageFile = new File(imagePath);
            return uploadToStorage(imageFile);
        } finally {
            // 清理临时文件
            new File(pdfPath).delete();
            new File(imagePath).delete();
        }
    }

    /**
     * 生成产品登记证书PDF
     */
    private static void generateCertificate(String outputPath,
                                            String backgroundImagePath,
                                            String fontPath,
                                            HwProductRegistCert productInfo) throws Exception {
        try (PDDocument document = new PDDocument()) {
            PDPage page = new PDPage(PDRectangle.A4);
            document.addPage(page);

            // 加载字体
            PDType0Font font = PDType0Font.load(document, new File(fontPath));

            // 加载背景图片
            PDImageXObject background = PDImageXObject.createFromFile(backgroundImagePath, document);

            try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
                // 1. 添加背景图片
                contentStream.drawImage(background, 0, 0,
                        page.getMediaBox().getWidth(),
                        page.getMediaBox().getHeight());

                // 2. 添加产品信息(标题和名称居中)
                addCenteredProductInfo(contentStream, page, productInfo, font);

                // 3. 添加其他产品信息
                addProductDetails(contentStream, page, productInfo, font);

                // 4. 添加底部信息
                addFooterInfo(contentStream, page, productInfo, font);
            }

            document.save(outputPath);
        }
    }

    /**
     * 添加居中显示的标题和产品名称
     */
    private static void addCenteredProductInfo(PDPageContentStream contentStream,
                                               PDPage page,
                                               HwProductRegistCert productInfo,
                                               PDType0Font font) throws IOException {
        float pageWidth = page.getMediaBox().getWidth();
        float centerX = pageWidth / 2;

        // 垂直起始位置(距顶部250px)
        float startY = page.getMediaBox().getHeight() - 250;

        // 1. 添加标题(36号字,居中)
        String title = "数据产品登记凭证";
        float titleWidth = calculateTextWidth(font, title, 36);
        contentStream.beginText();
        contentStream.setFont(font, 36);
        contentStream.newLineAtOffset(centerX - titleWidth/2, startY);
        contentStream.showText(title);
        contentStream.endText();

        // 2. 添加产品名称(28号字,居中,距标题60px)
        String name = productInfo.getName();
        float nameWidth = calculateTextWidth(font, name, 28);
        contentStream.beginText();
        contentStream.setFont(font, 28);
        contentStream.newLineAtOffset(centerX - nameWidth/2, startY - 60);
        contentStream.showText(name);
        contentStream.endText();
    }

    /**
     * 添加产品详细信息
     */
    private static void addProductDetails(PDPageContentStream contentStream,
                                          PDPage page,
                                          HwProductRegistCert productInfo,
                                          PDType0Font font) throws IOException {
        float startY = page.getMediaBox().getHeight() - 400; // 从标题下移150px开始
        float lineHeight = 40;

        // 左侧对齐,距左边150px
        addFormattedLine(contentStream, "登记编号:", productInfo.getCode(), 100, startY, font, 20);
        addFormattedLine(contentStream, "登记日期:", productInfo.getCreateDate(), 100, startY - lineHeight, font, 20);
        addFormattedLine(contentStream, "登记机构:", productInfo.getOrgName(), 100, startY - lineHeight * 2, font, 20);
        addFormattedLine(contentStream, "数据产品持有者:", productInfo.getSupplierName(), 100, startY - lineHeight * 3, font, 20);
        addFormattedLine(contentStream, "统一社会信用代码:", productInfo.getShxydm(), 100, startY - lineHeight * 4, font, 20);
    }

    /**
     * 添加底部信息(右侧对齐)
     */
    private static void addFooterInfo(PDPageContentStream contentStream,
                                      PDPage page,
                                      HwProductRegistCert productInfo,
                                      PDType0Font font) throws IOException {
        float pageWidth = page.getMediaBox().getWidth();
        float rightMargin = 100; // 右侧边距100px

        // 1. 大写登记日期(底部右侧,距底部120px)
        String createDateUpper = productInfo.getCreateDateUppercase();
        float dateUpperWidth = calculateTextWidth(font, createDateUpper, 22);
        contentStream.beginText();
        contentStream.setFont(font, 22);
        contentStream.newLineAtOffset(pageWidth - dateUpperWidth - rightMargin, 120);
        contentStream.showText(createDateUpper);
        contentStream.endText();

        // 2. 登记日期(底部右侧,距大写日期上方30px)
        String orgName = productInfo.getOrgName();
        float dateWidth = calculateTextWidth(font, orgName, 22);
        contentStream.beginText();
        contentStream.setFont(font, 22);
        contentStream.newLineAtOffset(pageWidth - dateWidth - rightMargin, 150);
        contentStream.showText(orgName);
        contentStream.endText();
    }

    /**
     * 添加格式化文本行(标签+值)
     */
    private static void addFormattedLine(PDPageContentStream contentStream,
                                         String label,
                                         String value,
                                         float x,
                                         float y,
                                         PDType0Font font,
                                         int fontSize) throws IOException {
        // 添加标签
        contentStream.beginText();
        contentStream.setFont(font, fontSize);
        contentStream.newLineAtOffset(x, y);
        contentStream.showText(label);
        contentStream.endText();

        // 添加值
        float labelWidth = calculateTextWidth(font, label, fontSize);
        contentStream.beginText();
        contentStream.setFont(font, fontSize);
        contentStream.newLineAtOffset(x + labelWidth, y);
        contentStream.showText(value);
        contentStream.endText();
    }

    /**
     * 将PDF转换为图片
     */
    private static void pdfToImage(String pdfPath, String imagePath) throws IOException {
        try (PDDocument document = PDDocument.load(new File(pdfPath))) {
            PDFRenderer renderer = new PDFRenderer(document);
            // 高质量渲染,300 DPI,RGB格式
            BufferedImage image = renderer.renderImageWithDPI(0, 300, ImageType.RGB);
            ImageIO.write(image, "PNG", new File(imagePath));
        }
    }

    /**
     * 上传图片到存储系统
     */
    private static String uploadToStorage(File imageFile) throws IOException {
        try (InputStream is = new FileInputStream(imageFile)) {
            Map<String, Object> result = ZosUtil.streamUpload(
                    is,
                    BussinessEnum.CERT.name(),
                    imageFile.getName(),
                    null
            );
            return result.get("fileUrl").toString();
        }
    }

    /**
     * 精确计算文本显示宽度
     */
    private static float calculateTextWidth(PDType0Font font, String text, float fontSize) throws IOException {
        return font.getStringWidth(text) / 1000 * fontSize;
    }

    /**
     * 产品信息实体类
     */
    @Data
    public static class ProductInfo {
        private String title;                  // 证书标题
        private String name;                   // 产品名称
        private String code;                   // 登记编号
        private String createDate;             // 登记日期
        private String createDateUppercase;    // 大写登记日期
        private String orgName;                // 登记机构
        private String supplierName;           // 数据产品持有者
        private String shxydm;                 // 统一社会信用代码
    }

    /**
     * 测试方法
     */
    public static void main(String[] args) {
        try {
            // 产品信息
            HwProductRegistCert productInfo = new HwProductRegistCert();

            productInfo.setName("燃气输送SCADA监测数据");
            productInfo.setCode("2025320100SJA0308");
            productInfo.setCreateDate("2025年05月16日");
            productInfo.setCreateDateUppercase("二〇二五年五月十六日");
            productInfo.setOrgName("南京市公共资源交易中心");
            productInfo.setSupplierName("江苏东能天然气管网有限公司");
            productInfo.setShxydm("91320623067634411F");

            // 文件路径配置
            String fontPath = "C:/Windows/Fonts/simhei.ttf"; // 黑体字体路径
            String backgroundPath = "C:/Users/dell/Desktop/1111/temp/certificate_bg.png"; // 背景图片路径

            // 生成并上传证书
            String imageUrl = generateCertificateAndUpload(productInfo, fontPath, backgroundPath);
            System.out.println("证书图片生成成功,URL: " + imageUrl);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

调用方式

 HwProductRegistCert cert=new HwProductRegistCert();
                    Date registFileCreateTime=new Date();
                    //费用账单号:FY+年月日时+6位随机数
                    Random random = new Random();
                    Integer cusCode = random.nextInt(900000) + 100000;
                    Optional<String> recNo = BatchNoUtils.createOrderNo("NJSJJY", cusCode);
                    recNo.ifPresent(code ->   {
                        cert.setCode(code);
                    });
                    cert.setName(hwAppliedGoods.getName());
                    cert.setOrgName(registOrgName);
                    cert.setCreateTime(registFileCreateTime);
                    HwRzCompany company=rzCompanyService.getById(hwAppliedGoods.getSupplierId());
                    if(!ObjectUtils.isEmpty(company)){
                        cert.setShxydm(company.getShxydm());
                        cert.setSupplierName(company.getName());
                    }
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
                    String createDate = sdf.format(registFileCreateTime);
                    String createDateUppercase= ChineseDateFormatter.formatToChinese(registFileCreateTime);
                    cert.setCreateDate(createDate);
                    cert.setCreateDateUppercase(createDateUppercase);
                    if("1".equals(hwAppliedGoods.getType())){
                        cert.setTitle("应用产品登记凭证");
                    }else{
                        cert.setTitle("服务产品登记凭证");
                    }
                    // 生成PDF并转为图片
                    String certUrl = Word2PDFUtils.generateCertificateAndUpload(cert, fontPath, backgroundPath);

你可能感兴趣的:(java,pdf)