Newer
Older
casic-metering / casic-metering-common / src / main / java / com / casic / missiles / utils / StampUtils.java
package com.casic.missiles.utils;


import cn.afterturn.easypoi.word.WordExportUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.casic.missiles.dto.business.certificate.ElectronicImage;
import com.casic.missiles.dto.business.certificate.FilePrintRegister;
import com.spire.doc.*;
import com.spire.doc.documents.*;
import com.spire.doc.fields.DocPicture;
import com.spire.doc.fields.TextRange;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.Map;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author:zt
 * @Create:2023/3/7/9:30
 * @Description:TODO Word文件操作工具类
 * @Version:1.0
 */

public class StampUtils {

    //关键字索引 (-1)
    private final static Integer keyWordIndex = -1;
    // 电子印章水平位置
    private final static float horizontal = 300f;
    //  电子印章垂直位置
    private final static float vertical = -55f;
    // 电子印章宽度
    private final static float stampWidth = 120;
    // 电子印章高度
    private final static float stampHeight = 120;
    //照片透明度设置
    private final static int alpha = 150;


    /**
     * @param filePrintRegister 标准文件注册表
     */
    public static void filePrintGenerate(FilePrintRegister filePrintRegister) throws RuntimeException {
        //1、按照模板填充数据,并导出word
        String wordOldUrl = exportWord(filePrintRegister.getTemplatePath(), filePrintRegister.getTemDir(), filePrintRegister.getFileName(), filePrintRegister.getParams());
        //设置透明属性  1、获取照片 2、签章背景透明设置 3、设置照片路径和照片类型进行图片保存
        for (ElectronicImage electronicSeal : filePrintRegister.getElectronicImageList()) {
            BufferedImage bi = readImage(electronicSeal.getElectronicSealImgeUrl());
            BufferedImage electronSealImage = convertLayout(bi, electronicSeal.getDiaphaneity());
            String stampImgUrl = electronicSeal.getElectronicSealImgeUrl();
            String imagePath = stampImgUrl.substring(0, stampImgUrl.length() - 4) + "1.png";
            String[] imageCutOffContents = stampImgUrl.split(".");
            electronicSeal.setElectronicSealImgeUrl(imagePath);
            saveFile(electronSealImage, imageCutOffContents[imageCutOffContents.length - 1], imagePath);
        }
        //按关键字进行分组
        Map<String, List<ElectronicImage>> sameKeySealMaps = filePrintRegister.getElectronicImageList().stream().collect(
                Collectors.groupingBy(ElectronicImage::getKeyWord)
        );
        // 初始化world,pdf名称参数
        String[] filePrintType = filePrintRegister.getTemplatePath().split(".");
        String wordNewUrl = filePrintRegister.getFileName() + filePrintType[filePrintType.length - 1];
        String pdfNewUrl = filePrintRegister.getFileName() + "pdf";
        //3、根据关键字进行添加签章和签字
        for (Map.Entry<String, List<ElectronicImage>> entry : sameKeySealMaps.entrySet()) {
            String mapKey = entry.getKey();
            List<ElectronicImage> electronicSeals = entry.getValue();
            addSameKeyWordStamp(wordOldUrl, wordNewUrl, electronicSeals);
        }
        // 4、将新word转化为pdf文件
        wordToPdf(wordNewUrl, pdfNewUrl);
    }

    /**
     * 按照模板 填充数据生成word  只支持docx
     *
     * @param templatePath 模板文件路径
     * @param temDir       生成文件的目录
     * @param fileName     生成文件名
     * @param params       参数
     */
    public static String exportWord(String templatePath, String temDir, String fileName, Map<String, Object> params) {
        Assert.notNull(templatePath, "模板路径不能为空");
        Assert.notNull(temDir, "临时文件路径不能为空");
        Assert.notNull(fileName, "导出文件名不能为空");
        Assert.isTrue(fileName.endsWith(".docx"), "word导出请使用docx格式");
        if (!temDir.endsWith("/")) {
            temDir = temDir + File.separator;
        }
        File dir = new File(temDir);
        if (!dir.getParentFile().exists()) {
            // 新建文件夹
            dir.getParentFile().mkdirs();
        }
        String tmpPath = "";
        try {
            XWPFDocument doc = WordExportUtil.exportWord07(templatePath, params);
            tmpPath = temDir + fileName;
            FileOutputStream fos = new FileOutputStream(tmpPath);
            doc.write(fos);
            fos.flush();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return tmpPath;
    }


    /**
     * 将相同关键字的印章添加到同一个位置进行打印
     * 1、根据关键词位置添加电子印章
     * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作
     *
     * @param wordOldUrl         word文件路径
     * @param wordNewUrl         新word文件路径
     * @param electronicSealList 电子印章信息
     */
    private static void addSameKeyWordStamp(String wordOldUrl, String wordNewUrl, List<ElectronicImage> electronicSealList) throws RuntimeException {
        // 加载文档
        Document document = new Document();
        document.loadFromFile(wordOldUrl);

        //获取关键字位置
        TextSelection[] textSelections = document.findAllString(electronicSealList.get(0).getKeyWord(), false, false);
        for (ElectronicImage electronicSeal : electronicSealList) {
            //加签章照片
            if (ObjectUtils.isEmpty(textSelections) || StringUtils.isEmpty(electronicSeal.getElectronicSealImgeUrl())) {
                throw new RuntimeException("image url is empty  or key word not exist in the word template ...");
            }
            Paragraph paragraph = textSelections[keyWordIndex > -1 ? 0 : textSelections.length - 1].getAsOneRange().getOwnerParagraph();
            //添加公司印章
            DocPicture docPicture = paragraph.appendPicture(electronicSeal.getElectronicSealImgeUrl());
            //设置图片位于文字顶层
            docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text);
            //指定电子章位置
            //水平位置
            docPicture.setHorizontalPosition(horizontal);
            //垂直位置
            docPicture.setVerticalPosition(vertical);
            //设置电子章大小
            docPicture.setWidth(stampWidth);
            docPicture.setHeight(stampHeight);
        }
        //保存添加电子章的Word文档
        document.saveToFile(wordNewUrl);
        document.dispose();
    }

    /**
     * 替换书签名位置文本内容
     *
     * @param document        word文档对象
     * @param bookmarkName    书签名
     * @param newBookmarkText 新文本内容
     */
    private void replaceBookmarkContent(Document document, String bookmarkName, String newBookmarkText) {
        //定位到指定书签位置
        BookmarksNavigator bookmarksNavigator = new BookmarksNavigator(document);
        bookmarksNavigator.moveToBookmark(bookmarkName);
        //用文本内容替换原有书签位置的文本,新替换的内容与原文格式一致
        bookmarksNavigator.replaceBookmarkContent(newBookmarkText, true);
    }

    /**
     * word转PDF
     *
     * @param wordNewUrl word文件路径
     * @param pdfNewUrl  存储新PDF文件路径
     */
    public static void wordToPdf(String wordNewUrl, String pdfNewUrl) {
//        将新Word文档转换为PDF文件
        Document document = new Document();
        document.loadFromFile(wordNewUrl);
        document.saveToFile(pdfNewUrl, FileFormat.PDF);
        document.dispose();
    }
    /**
     * 图片透明背景转换
     *
     * @param imgsrc
     * @param alpha
     * @return
     */
    public static BufferedImage convertLayout(BufferedImage imgsrc, int alpha) {
        try {
            //创建一个包含透明度的图片,半透明效果必须要存储为png合适才行,存储为jpg,底色为黑色
            BufferedImage back = new BufferedImage(imgsrc.getWidth(), imgsrc.getHeight(), BufferedImage.TYPE_INT_ARGB);
            int width = imgsrc.getWidth();
            int height = imgsrc.getHeight();
            for (int j = 0; j < height; j++) {
                for (int i = 0; i < width; i++) {
                    int rgb = imgsrc.getRGB(i, j);
                    Color color = new Color(rgb);
                    Color newcolor = new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha);
                    back.setRGB(i, j, newcolor.getRGB());
                }
            }
            return back;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //读取图片
    private static BufferedImage readImage(String imgpath) {
        try {
            BufferedImage bufferedImage = ImageIO.read(new File(imgpath));
            return bufferedImage;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //保存图片,extent为格式,"jpg"、"png"等
    private static void saveFile(BufferedImage img, String extent, String newfile) {
        try {
            ImageIO.write(img, extent, new File(newfile));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    /**
     * 1、自定义位置添加电子印章
     * 2、替换书签名位置文本内容 bookmarkName传参为null,则不进行书签替换操作
     *
     * @param wordOldUrl      word文件路径
     * @param wordNewUrl      新word文件路径
     * @param stampImgUrl     电子印章图片路径
     * @param horizontal      电子印章水平位置 (当前文件推荐260f)
     * @param vertical        电子印章垂直位置 (当前推荐455f)
     * @param stampWidth      电子印章宽度(推荐120)
     * @param stampHeight     电子印章高度(推荐120)
     * @param bookmarkName    书签名,通过名称寻找书签文本所在位置
     * @param newBookmarkText 替换的文本新内容
     */
    public void addStamp(String wordOldUrl, String wordNewUrl, String stampImgUrl,
                         Float horizontal, Float vertical, Float stampWidth,
                         Float stampHeight, String bookmarkName, String newBookmarkText) {
        //        加载文档
        Document document = new Document();
        document.loadFromFile(wordOldUrl);
        //获取指定段落
        Section section = document.getSections().get(0);
        //获取段落总数
        int count = section.getParagraphs().getCount();
        //log.info("获取文档内容段落总数{}",count);
        Paragraph paragraph = section.getParagraphs().get(0);

        //        判断是否需要替换书签位置文本内容
        if (StringUtils.isNotEmpty(bookmarkName)) {
            replaceBookmarkContent(document, bookmarkName, newBookmarkText);
        }

//        添加电子印章
        DocPicture docPicture = paragraph.appendPicture(stampImgUrl);

//        指定电子章位置
//        水平位置
        docPicture.setHorizontalPosition(horizontal);
//        垂直位置
        docPicture.setVerticalPosition(vertical);

//        设置电子章大小
        docPicture.setWidth(stampWidth);
        docPicture.setHeight(stampHeight);

//        设置图片位于文字顶层
        docPicture.setTextWrappingStyle(TextWrappingStyle.In_Front_Of_Text);

        //        保存添加电子章的Word文档
        document.saveToFile(wordNewUrl);
        document.dispose();
//      log.info("文档添加电子印章结束,新WORD文档地址:{}",wordNewUrl);

    }


    /**
     * 替换书签名位置文本内容为图片
     *
     * @param document     word文档对象
     * @param bookmarkName 书签名
     * @param newImgUrl    图片地址
     */
    public void replaceBookmarkContentToImg(Document document, String bookmarkName, String newImgUrl) {
        //定位到指定书签位置
        BookmarksNavigator bookmarksNavigator = new BookmarksNavigator(document);
        bookmarksNavigator.moveToBookmark(bookmarkName);
        //添加图片,替换原有书签内容
        Paragraph para = new Paragraph(document);
        para.appendPicture(newImgUrl);
        TextBodyPart bodyPart = new TextBodyPart(document);
        bodyPart.getBodyItems().add(para);
        bookmarksNavigator.replaceBookmarkContent(bodyPart);
    }

    /**
     * 替换书签名位置文本内容为表格
     *
     * @param document     word文档对象
     * @param bookmarkName 书签名
     */
    public void replaceBookmarkContentToTable(Document document, String bookmarkName) {
        //声明数组内容
        String[][] data =
                {
                        new String[]{"分类", "等级", "编号"},
                        new String[]{"A", "一级", "01A"},
                        new String[]{"B", "二级", "02B"},
                        new String[]{"C", "三级", "03C"},
                };

        //创建表格
        Table table = new Table(document, true);
        table.resetCells(4, 3);
        for (int i = 0; i < data.length; i++) {
            TableRow dataRow = table.getRows().get(i);
            for (int j = 0; j < data[i].length; j++) {
                TextRange range = dataRow.getCells().get(j).addParagraph().appendText(data[i][j]);
                range.getOwnerParagraph().getFormat().setHorizontalAlignment(HorizontalAlignment.Center);
                range.getCharacterFormat().setFontName("楷体");
                dataRow.getRowFormat().setHorizontalAlignment(RowAlignment.Center);
                dataRow.getCells().get(j).getCellFormat().setVerticalAlignment(VerticalAlignment.Middle);
            }
        }

        //创建TextBodyPart对象
        TextBodyPart bodyPart = new TextBodyPart(document);
        bodyPart.getBodyItems().add(table);

        //定位到指定书签位置
        BookmarksNavigator bookmarkNavigator = new BookmarksNavigator(document);
        bookmarkNavigator.moveToBookmark(bookmarkName);

        //使用表格替换原书签的内容
        bookmarkNavigator.replaceBookmarkContent(bodyPart);
    }

    /**
     * 文件转流
     *
     * @param wordNewUrl
     * @return
     */
    public byte[] getBytesByFile(String wordNewUrl) {
        try {
//            byte[] bytes = Files.readAllBytes(Paths.get(wordNewUrl));
            File file = new File(wordNewUrl);
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            byte[] b = new byte[1024];
            int len = -1;
            while ((len = fis.read(b)) != -1) {
                bos.write(b, 0, len);
            }
            fis.close();
            bos.close();
            byte[] bytes = bos.toByteArray();
            System.out.println("successful...");
            return bytes;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 流转文件
     *
     * @param buf      流字节数组
     * @param filePath 新文件路径
     * @param fileName 新文件名称
     */
    public void byte2File(byte[] buf, String filePath, String fileName) {
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file = null;
        try {
            File dir = new File(filePath);
            if (!dir.exists() && dir.isDirectory()) {
                dir.mkdirs();
            }
            file = new File(filePath + File.separator + fileName);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(buf);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) throws RuntimeException {

        String pathUrl = "D:\\cz\\upload";

        //文件与BufferedImage间的转换
        //读取图片
        BufferedImage bi = readImage(pathUrl + "\\sign1.png");
        BufferedImage bii = convertLayout(bi, alpha);
        //生成透明背景图片
        saveFile(bii, "PNG", pathUrl + "\\sign3.png");

        //文件与BufferedImage间的转换
        //读取图片
        BufferedImage b = readImage(pathUrl + "\\name1.png");
        BufferedImage b0 = convertLayout(b, alpha);
        //生成透明背景图片
        saveFile(b0, "PNG", pathUrl + "\\name3.png");

        // 目标文件地址
        String wordOldUrl = pathUrl + "\\wordExport.docx";

        // 添加电子印章后文件存放地址
        String wordNewUrl = pathUrl + "\\tem.docx";
        //WORD转PDF存放位置
        String pdfNewUrl = pathUrl + "\\tem.pdf";
        //电子印章图片地址
        String stampImgUrl = pathUrl + "\\sign3.png";
        //电子签名图片地址
        String stampImgUrl1 = pathUrl + "\\name3.png";
        // word文档内容关键字
        String keyWord = "盖章";
        StampUtils addStampUtils = new StampUtils();
        List<ElectronicImage> electronicSealList = new ArrayList(11);
        int count = 0;
        for (; count < 2; count++) {
            ElectronicImage electronicSeal = new ElectronicImage();
            String tempStampImgUrl = count == 0 ? stampImgUrl : stampImgUrl1;
            electronicSeal.setElectronicSealImgeUrl(tempStampImgUrl);
            electronicSeal.setMereFlag(count == 1);
            electronicSeal.setKeyWord(keyWord);
            electronicSeal.setKeyWordIndex(keyWordIndex);
            electronicSeal.setHorizontal(horizontal);
            electronicSeal.setVertical(vertical);
            electronicSeal.setStampHeight(stampHeight);
            electronicSeal.setStampWidth(stampWidth);
            electronicSealList.add(electronicSeal);
        }
        addSameKeyWordStamp(wordOldUrl, wordNewUrl, electronicSealList);
        // 将新word转化为pdf文件
        addStampUtils.wordToPdf(wordNewUrl, pdfNewUrl);
    }
}