word模版字段渲染、拼接、转pdf、加图片水印、最后再加密

package com.gw.crm.doc.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.aspose.words.Document;
import com.aspose.words.FontSettings;
import com.aspose.words.ImportFormatMode;
import com.aspose.words.SaveFormat;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.plugin.table.HackLoopTableRenderPolicy;
import com.gw.crm.doc.util.StringUtil;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.*;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class Test {


    public static void main(String[] args) throws Exception {
        String data = "{\n" +
                "\t\"appendix\": [{\n" +
                "\t\t\"appendixId\": \"84a306bc270a4c75aef82e72cc7706de\",\n" +
                "\t\t\"appendixVars\": {}\n" +
                "\t}, {\n" +
                "\t\t\"appendixId\": \"84a306bc270a4c75aef82e72cc7706d\",\n" +
                "\t\t\"appendixVars\": {}\n" +
                "\t}, {\n" +
                "\t\t\"appendixId\": \"84a306bc270a4c75aef82e72cc770\",\n" +
                "\t\t\"appendixVars\": {\n" +
                "\t\t\t\"speEquipment_finalUser_name\": \"\",\n" +
                "\t\t\t\"speEquipment_finalUser_address\": \"\",\n" +
                "\t\t\t\"speEquipment_finalUser_contactName\": \"\",\n" +
                "\t\t\t\"speEquipment_finalUser_contactPhone\": \"\",\n" +
                "\t\t\t\"speEquipment_sellerName\": \"\",\n" +
                "\t\t\t\"speEquipment_sellerAddress\": \"\",\n" +
                "\t\t\t\"speEquipment_sellerContactName\": \"\",\n" +
                "\t\t\t\"speEquipment_sellerContactPhone\": \"\",\n" +
                "\t\t\t\"speEquipment_user_governOrg\": \"\",\n" +
                "\t\t\t\"speEquipment_user_secretQualityOrg\": \"\",\n" +
                "\t\t\t\"speEquipment_user_safeQualityOrg\": \"\",\n" +
                "\t\t\t\"speEquipment_user_elseOrg\": \"\",\n" +
                "\t\t\t\"speEquipment_seller_promise\": \"\",\n" +
                "\t\t\t\"speEquipment_seller_signName\": \"\",\n" +
                "\t\t\t\"speEquipment_seller_signTime\": \"\"\n" +
                "\t\t}\n" +
                "\t}, {\n" +
                "\t\t\"appendixId\": \"0644fedd6d054fc8805acbe0b88c87b7\",\n" +
                "\t\t\"appendixVars\": {}\n" +
                "\t}],\n" +
                "\t\"contractId\": \"0005e63b4cfe4ce3ad7eee58586379c3\",\n" +
                "\t\"contractName\": \"销售类合同-宁都东芯科技有限公司-河北移动合同流程测试项目-20221228\",\n" +
                "\t\"contractVars\": {\n" +
                "\t\t\"second_taxRate\": \"\",\n" +
                "\t\t\"first_payPart_scale\": \"\",\n" +
                "\t\t\"quality_inspection_time\": \"5\",\n" +
                "\t\t\"first_pay_month\": \"\",\n" +
                "\t\t\"contract_copies\": \"\",\n" +
                "\t\t\"second_contactEmail\": \"sdsda.qq.8520\",\n" +
                "\t\t\"first_payAll_time\": \"\",\n" +
                "\t\t\"second_sign_year\": \"\",\n" +
                "\t\t\"first_payment_typeNumber\": \"\",\n" +
                "\t\t\"second_accountName\": \"张晓\",\n" +
                "\t\t\"first_contractCopies\": \"\",\n" +
                "\t\t\"speEquipment_letter\": true,\n" +
                "\t\t\"overDue_pay_time\": \"10\",\n" +
                "\t\t\"second_contactAddress\": \"北京\",\n" +
                "\t\t\"second_bankName\": \"中国人民银行之西城区分行\",\n" +
                "\t\t\"first_bankName\": \"\",\n" +
                "\t\t\"contract_upperMoney\": \"柒拾万元整\",\n" +
                "\t\t\"first_name\": \"\",\n" +
                "\t\t\"first_contactPhone\": \"852020\",\n" +
                "\t\t\"first_accountNumber\": \"\",\n" +
                "\t\t\"first_contactEmail\": \"1144981288@qq.com\",\n" +
                "\t\t\"second_accountNumber\": \"1\",\n" +
                "\t\t\"notSecret_scale\": \"6\",\n" +
                "\t\t\"second_contractCopies\": \"\",\n" +
                "\t\t\"first_payPart_time\": \"\",\n" +
                "\t\t\"export_control_letter\": true,\n" +
                "\t\t\"first_payRest_time\": \"\",\n" +
                "\t\t\"first_pay_year\": \"\",\n" +
                "\t\t\"first_contactName\": \"张三\",\n" +
                "\t\t\"second_contactName\": \"赵苏\",\n" +
                "\t\t\"first_taxNumber\": \"\",\n" +
                "\t\t\"speEquipment_finalUser_register\": true,\n" +
                "\t\t\"second_sign_day\": \"\",\n" +
                "\t\t\"first_contactAddress\": \"银谷大厦\",\n" +
                "\t\t\"contract_money\": 700000,\n" +
                "\t\t\"first_pay_day\": \"\",\n" +
                "\t\t\"firt_payment_type\": \"1\",\n" +
                "\t\t\"receipt\": true,\n" +
                "\t\t\"firt_payment_else\": \"\",\n" +
                "\t\t\"second_sign_month\": \"\",\n" +
                "\t\t\"second_contactPhone\": \"85200\",\n" +
                "\t\t\"firt_payment_typeElse\": \"\",\n" +
                "\t\t\"transport_typeNumber\": null,\n" +
                "\t\t\"delivery_typeNumber\": \"1\",\n" +
                "\t\t\"send_place\": \"上海外滩十八号\",\n" +
                "\t\t\"first_delivery_receiverName\": \"赵武\",\n" +
                "\t\t\"first_delivery_receiverPhone\": \"12520000\",\n" +
                "\t\t\"contract_first_party\": \"宁都东芯科技有限公司\",\n" +
                "\t\t\"contract_second_party\": \"中国长城科技集团股份有限公司\",\n" +
                "\t\t\"proj_name\": \"河北移动合同流程测试项目\",\n" +
                "\t\t\"productList\": [{\n" +
                "\t\t\t\"index\": 1,\n" +
                "\t\t\t\"name\": \"标配产品4\",\n" +
                "\t\t\t\"configure\": \"\",\n" +
                "\t\t\t\"customized\": \"√是□否\",\n" +
                "\t\t\t\"zxyProduct\": \"□是√否\",\n" +
                "\t\t\t\"pnCode\": \"5181809\",\n" +
                "\t\t\t\"price\": 7000,\n" +
                "\t\t\t\"count\": 50,\n" +
                "\t\t\t\"totalAmountExcludingTax\": \"--\",\n" +
                "\t\t\t\"totalAmountIncludingTax\": 350000\n" +
                "\t\t}]\n" +
                "\t},\n" +
                "\t\"contract_conf_id\": \"2c46bac81a7742ddbf1512e279ab1c9f\"\n" +
                "}";
        JSONObject param = JSONObject.parseObject(data);
        String contractId = param.getString("contract_conf_id");
        String contractName = param.getString("contractName");
        JSONObject jsonObject = param.getJSONObject("contractVars");
        String contractVars = jsonObject.toJSONString();
        Map<String, Object> jsonMap = JSON.parseObject(contractVars, new TypeReference<HashMap<String, Object>>() {});

        String template = "/word/20221229/2022122916464428_20221228版本产品销售合同正文.docx";
        String templateDirectory = "/Users/fukui/IdeaProjects/xc-crm/crm-doc/src/main/resources";
        template = templateDirectory + template;
        String dest = getOutputTemporaryFile(template);
        String  contract = genDocxTemplate(template,dest,jsonMap,"productList");
        String outPut = getOutputFile(template,contractName);
        appendToOneDoc(contract,outPut);

        JSONArray jsonA = param.getJSONArray("appendix");
        if(jsonA == null || jsonA.isEmpty() || jsonA.size()<1){
        }else {
            for (int i=0;i< jsonA.size();i++){
                String appendixVars = jsonA.getJSONObject(i).getJSONObject("appendixVars").toJSONString();//附件内容
                Map<String, Object> jsonFu1 = JSON.parseObject(appendixVars, new TypeReference<HashMap<String, Object>>() {});

                String templatFu = "";
                if (i==0){
                    templatFu = "/word/20221228160854709_附件1出口管制承诺函(1).docx";
                }
                if (i==1){
                    templatFu = "/word/20221228160909649_附件2专用信息设备销售和使用承诺.docx";
                }
                if (i==2){
                    templatFu = "/word/20221228160924328_附件3专用信息设备最终用户情况登记表(1).docx";
                }
                if (i==3){
                    templatFu = "/word/20221228160938733_附件4签收单(1).docx";
                }
                templatFu = templateDirectory + templatFu;
                String destFu = getOutputTemporaryFile(templatFu);
                String  enclosure = genDocxTemplate(templatFu,destFu,jsonFu1,"productList");
                threeDocToOneDoc(enclosure,outPut);
            }
        }
        String outPdf = outPut.replace(".docx",".pdf");
        docxToPdf(outPut,outPdf);
        Files.deleteIfExists(Paths.get(outPut));
        String finaPutPath = outPdf.replace("删除文字","");
        Boolean addWaterMark = genPdfTemplatePicture(outPdf, finaPutPath);
        Files.deleteIfExists(Paths.get(outPdf));
        encryptionPdf(finaPutPath,"admin");
    }

    /**
     * 拼接生成输出文件路径.
     */
    private static String getOutputFile(String template,String name) throws Exception {
        if (StringUtil.isEmpty(template)) {
            throw new Exception("模板路径不能为空");
        }
        //截取模板文件名称
        SimpleDateFormat sdf_time = new SimpleDateFormat("HHmmssS");
        //拼接输出文件名称
        String output_fileName = name + "_" + "删除文字" + sdf_time.format(new Date()) + ".docx";
        SimpleDateFormat sdf_date = new SimpleDateFormat("yyyyMMdd");
        //拼接输出文件全路径
        String outputFolder = "/Users/fukui/IdeaProjects/xc-crm/crm-doc/src/main/resources";
        String output_fullFolder = outputFolder + File.separator  + sdf_date.format(new Date());
        //如果目录不存在,就创建目录
        File output_fileFolder = new File(output_fullFolder);
        if (!output_fileFolder.exists()) {
            output_fileFolder.mkdirs();
        }
        return output_fullFolder + File.separator + output_fileName;
    }

    /**
     * 拼接生成合同、附件输出文件路径.
     */
    private static String getOutputTemporaryFile(String template) throws Exception {
        if (StringUtil.isEmpty(template)) {
            throw new Exception("模板路径不能为空");
        }
        //截取模板文件名称
        String template_fileName = template.substring(template.lastIndexOf("/") + 1,template.lastIndexOf("."));
        SimpleDateFormat sdf_time = new SimpleDateFormat("HHmmssS");
        //拼接输出文件名称
        String output_fileName = template_fileName + "_" + sdf_time.format(new Date()) ;
        SimpleDateFormat sdf_date = new SimpleDateFormat("yyyyMMdd");
        //拼接输出文件全路径
        String outputFolder = "/Users/fukui/IdeaProjects/xc-crm/crm-doc/src/main/resources";
        String output_fullFolder = outputFolder + File.separator + "temporary"+ File.separator  + sdf_date.format(new Date());
//        如果目录不存在,就创建目录
        File output_fileFolder = new File(output_fullFolder);
        if (!output_fileFolder.exists()) {
            output_fileFolder.mkdirs();
        }
        return output_fullFolder + File.separator + output_fileName;
    }

    /**
     * 不加水印
     * @param template
     * @param dest
     * @param vars
     * @param tableField
     * @return
     */
    public static String genDocxTemplate(String template, String dest, Map<String, Object> vars, String tableField) {
        File file = new File(dest);
        if (file.isDirectory() && !file.exists()) {
            file.mkdirs();
        }
        String dest_docx = dest + ".docx";
        try {
            genDocxOnTemplate(template, dest_docx, vars, tableField);
            Document doc = new Document(dest_docx);
            doc.save( dest_docx );
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dest_docx;
    }

    /**
     * 基于docx模版生成docx文档,支持表格动态渲染。
     *
     * @param template   模版文件路径
     * @param dest       结果文件路径
     * @param vars       变量数据
     * @param tableField 表格域名称
     * @return 成功:true,失败:false
     */
    public static boolean genDocxOnTemplate(String template, String dest, Map<String, Object> vars, String tableField) {
        try {
            HackLoopTableRenderPolicy policy = new HackLoopTableRenderPolicy();
            XWPFTemplate compile;
            if (tableField != null) {
                Configure config = Configure.newBuilder().bind(tableField, policy).build();
                compile = XWPFTemplate.compile(template, config);
            } else {
                compile = XWPFTemplate.compile(template);
            }
            compile.render(vars);
            compile.writeToFile(dest);
            return true;
        } catch (IOException e) {
//            logger.error(e.getMessage(),e);
        }
        return false;
    }

    /**
     * 根据 inputContractWord 文件生成 outContractWord 文件
     * inputContractWord 要合并的合同
     * outContractWord 最终输出的拼接后的合同
     * @throws Exception
     */
    public static void appendToOneDoc(String inputContractWord,String outContractWord) throws Exception {
        Document doc2 = new Document(inputContractWord);
        Document doc4 = new Document();
        doc4.removeAllChildren();
        doc4.appendDocument( doc2, ImportFormatMode.KEEP_DIFFERENT_STYLES );
        doc4.save(outContractWord);
    }

    /**
     * 将docx文档转化为pdf文件。
     *
     * @param docxPath docx文档
     * @param outPath  pdf文档
     * @return 成功:true,失败:false
     */
    public static boolean docxToPdf(String docxPath, String outPath) {
        FileOutputStream os = null;
        try {
            File file = new File(outPath);
            os = new FileOutputStream(file);
            Document doc = new Document(docxPath);
            Document _doc = new Document(docxPath);
            doc.copyStylesFromTemplate(_doc);
            FontSettings.getDefaultInstance().setFontsFolder("/Users/fukui/IdeaProjects/xc-crm/crm-doc/src/main/resources/tiff", true);
            doc.save(os, SaveFormat.PDF);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            if (os != null) {
                try {
                    os.flush();
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return true;
    }

    /**
     * 把 inputContractWord 文件合并到 outContractWord 里面
     * inputContractWord 要合并的合同
     * inputEnclosureWord 要合并的附件
     * outContractWord 最终输出的拼接后的合同
     * @throws Exception
     */
    public static void threeDocToOneDoc(String inputContractWord,String outContractWord) throws Exception {
        Document doc1 = new Document(outContractWord);
        Document doc2 = new Document(inputContractWord);
        Document doc4 = new Document();

        doc4.removeAllChildren();
        doc4.appendDocument( doc1, ImportFormatMode.USE_DESTINATION_STYLES );
        doc4.appendDocument( doc2, ImportFormatMode.USE_DESTINATION_STYLES );
        doc4.save(outContractWord);
    }

    /**
     * 加图片水印.
     */
    public static boolean genPdfTemplatePicture(String inputFile, String outputFile) {
        try {
            String inputImage = "/Users/fukui/IdeaProjects/xc-crm/crm-doc/src/main/resources/word/77.png";
//            imageFileWaterPrint(inputImage,inputFile, outputFile);
//            return addWaterMark(inputFile, outputFile, inputImage, 130, 40, 4, 3, 30, 0.1f);
            addWaterMark(inputFile, outputFile, "/Users/fukui/IdeaProjects/xc-crm/crm-doc/src/main/resources/word/77.png", 78, 300, 30, 0.1f);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    //加图片水印
    public static boolean addWaterMark(String inputFile,String outputFile,
                                       String picFilePath, float picHeight, float picWidth, int picRowNum, int picColNum,
                                       int rotateDegree, float transDegree) {
        try {
            PdfReader reader = new PdfReader(inputFile);
            PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputFile));
            int total = reader.getNumberOfPages() + 1;
            PdfContentByte watermark;
            // 遍历pdf文件的每页以处理
            for (int i = 1; i < total; i++) {
                // 获得PDF最顶层
                watermark = stamper.getOverContent(i);  //在内容上方加水印
                watermark.saveState();
                PdfGState gs = new PdfGState();
                // 设置透明度范围为0到1
                gs.setFillOpacity(transDegree);
                watermark.setGState(gs);
                watermark.beginText();
                watermark.setColorFill(BaseColor.BLACK);    //字体颜色
                // 计算水印X,Y坐标
                float x = reader.getPageSize(i).getWidth() / (picColNum+1);
                float y = reader.getPageSize(i).getHeight() / (picRowNum+1);
                for (int col = 1; col < picColNum+1; col++) {
                    for (int row = 1; row < picRowNum+1; row++) {
                        // 设置文字水印
                        if (picFilePath != null || !"".contentEquals(picFilePath)) {
                            // 设置图片水印
                            com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance(picFilePath);
                            image.setAbsolutePosition(col*x, row*y);    // 设置坐标 绝对位置 X Y
                            image.setRotationDegrees(rotateDegree);     // 旋转 角度
//                            image.scaleAbsolute(picHeight, picWidth);   // 自定义大小
                            image.scalePercent(5);   // 原来图像的比例
                            watermark.setGState(gs);    // 设置透明度
                            watermark.addImage(image);  // 添加水印图片
                        }
                    }
                }
                watermark.endText();
                watermark.setLineWidth(1f);
                watermark.stroke();
            }
            stamper.close();
            reader.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 加图片水印
     */
    public static boolean addWaterMark(String inputFile, String outputFile, String picFilePath, float picHeight, float picWidth, int rotateDegree, float transDegree) {
        try {
            PdfReader reader = new PdfReader(inputFile);
            PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputFile));
            int total = reader.getNumberOfPages() + 1;
            PdfContentByte watermark;
            int count = 0;
            // 遍历pdf文件的每页以处理
            for (int i = 1; i < total; i++) {
                // 获得PDF最顶层
                watermark = stamper.getUnderContent(i);
                watermark.saveState();
                PdfGState gs = new PdfGState();
                // 设置透明度范围为0到1
                gs.setFillOpacity(transDegree);
                watermark.setGState(gs);
                watermark.beginText();
                // 计算水印X,Y坐标
                float scale = 1.8f;
                float pageHeight = reader.getPageSize(i).getHeight();
                float pageWidth = reader.getPageSize(i).getWidth();
                float inW = picWidth / scale;
                float inH = picHeight / scale;
                for (int col = 0; col < 50; col++) {
                    float x = (col * inW) - inW / 2;
                    if (x > 0) {
                        x += col * inW * 0.8f;
                    }
                    if (x > pageWidth) {
                        break;
                    }
                    for (int row = 0; row < 50; row++) {
                        float y = row * inH + 2f * inH;
                        if (y > 0) {
                            y += row * inH * 5.5f;
                        }
                        if (y > pageHeight) {
                            break;
                        }

                        if (x + inW < 0 || y + inH < 0 || x > pageWidth || y > pageHeight) {
                            continue;
                        }
                        // 设置图片水印
                        com.itextpdf.text.Image image = com.itextpdf.text.Image.getInstance(picFilePath);
                        // 原来图像的比例
                        image.scaleAbsolute(inW, inH);
                        // 设置透明度
                        watermark.setGState(gs);
                        // 设置坐标 绝对位置 X Y
                        image.setAbsolutePosition(x, y);
                        // 旋转 角度
                        image.setRotationDegrees(rotateDegree);
                        // 添加水印图片
                        watermark.addImage(image);
                        count++;
                    }
                }
                watermark.endText();
                watermark.setLineWidth(1f);
                watermark.stroke();
            }
            stamper.close();
            reader.close();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    //加密pdf
    public static void encryptionPdf(String  inPutFile,String password) throws FileNotFoundException, DocumentException {
        try {
            InputStream is = new FileInputStream(new File(inPutFile));
            PdfReader pdfReader = new PdfReader(is);
            PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileOutputStream(inPutFile));
            pdfStamper.setEncryption(password.getBytes(), null, 0, PdfWriter.ENCRYPTION_AES_256);
            pdfStamper.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

下面是对应的pom文件

<dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.10</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
        <dependency>
            <groupId>fr.opensagres.xdocreport</groupId>
            <artifactId>fr.opensagres.poi.xwpf.converter.pdf</artifactId>
            <version>2.0.1</version>
            <exclusions>
                <exclusion>
                    <artifactId>2.1.7</artifactId>
                    <groupId>fr.opensagres.xdocreport.itext</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.aspose.words</groupId>
            <artifactId>aspose-words</artifactId>
            <version>19.5</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/resources/lib/aspose-words-19.5.jar</systemPath>
        </dependency>

下面是目录结构
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值