百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

干货Java轻松搞定word转pdf,替换占位符+个性水印

toyiye 2024-06-21 12:28 7 浏览 0 评论

背景介绍

在实际的项目当中,有很多这样的场景,管理后台上传word模板文件(如协议、合同、通知书等),需要通过代码实现,将业务数据写入到word文件的不同位置,然后生成pdf文件并上传到文件服务器,提供用户下载或者预览的功能。比如:用户在某平台借款,生成的借款协议。

插件下载与安装

本文主要使用 Aspose.Words 实现word转pdf,通过替换word中的占位符实现文件中数据的更新。更多功能可以参考Aspose官方网站。

  • 插件下载

链接:https://pan.baidu.com/s/1TbkczJNSN9X8LjV5L49ssw

提取码:vspw

官网下载地址:https://www.aspose.com/

  • 插件安装

下载的jar包,可以直接放到java项目当中,也可以上传到maven私服追加pom引用。

效果展示

  • 原word文件,有year、month、day、user_name四个占位符

  • 转换后的PDF文件,占位符信息已更新,并追加了水印

代码逻辑

import com.aspose.words.Shape;
import com.aspose.words.*;

import java.awt.*;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author luandy
 * @create 2021/02/28 12:43
 */
public class TestWordsToPdf {
    /** isMatchCase 是否区分大小写 */
    private static final boolean IS_MATCH_CASE_TRUE = true;
    /** isMatchWholeWord 是否全词匹配 */
    private static final boolean IS_MATCH_WHOLE_WORD_TRUE = false;

    /** 字体目录:mac系统,根据系统字体目录调整 */
    private static final String FONT_FOLDER = "/System/Library/Fonts";

    /**
     * 测试方法
     *
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        String wordPath = "/Users/luandy/Downloads/模板_V1.0.docx";
        String pdfPath = "/Users/luandy/Downloads/模板_V1.0." + System.currentTimeMillis() + ".pdf";

        ConcurrentHashMap<String, String> dataMap = new ConcurrentHashMap();
        dataMap.put("year", "2021");
        dataMap.put("month", "2");
        dataMap.put("day", "28");
        dataMap.put("user_name", "我是八零后琐话,欢迎您的关注");

        // word转换pdf
        docToPdf(wordPath, pdfPath, dataMap);
    }

    /**
     * word转pdf主方法
     * 
     * @param wordPath
     * @param pdfPath
     * @param dataMap
     * @return
     * @throws Exception
     */
    public static boolean docToPdf(String wordPath, String pdfPath, ConcurrentHashMap<String, String> dataMap) throws Exception {
        // 验证License 若不验证则转化出的pdf文档会有水印产生
        if (!isWordLicense()) {
            System.out.println("License验证不通过...");
            return false;
        }
        File pdfFile = null;
        FileOutputStream pdfFos = null;
        try {
            long old = System.currentTimeMillis();
            // 新建一个pdf文档
            pdfFile = new File(pdfPath);
            pdfFos = new FileOutputStream(pdfFile);
            // 将要被转化的word文档
            Document doc = new Document(wordPath);
            // 字体设置
            FontSettings.setFontsFolder(FONT_FOLDER + File.separator, true);
            // Aspose.Words 使用Replace()对模板进行替换字符操作
            replaceWordsKey(doc, dataMap);
            // 为PDF追加水印
            insertWaterMarkText(doc, "八零后琐话");
            // 全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换
            doc.save(pdfFos, SaveFormat.PDF);
            long now = System.currentTimeMillis();
            System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒");
        } catch (Exception e) {
            System.out.println("Word 转 Pdf 失败..." + e);
            // 为了不生成空文件,出现异常时,删除pdf文件,以便重新生成
            if (pdfFile != null) {
                pdfFile.delete();
            }
            return false;
        } finally {
            if (pdfFos != null) {
                pdfFos.close();
            }
        }
        // 文件转换成功
        return true;
    }

    /**
     * 替换Word中的占位符
     *
     * @param doc
     * @param dataMap
     * @throws Exception
     */
    private static void replaceWordsKey(Document doc, ConcurrentHashMap<String, String> dataMap) throws Exception {
        for (Map.Entry<String, String> entry : dataMap.entrySet()) {
            // 替换Word中的变量,longfor_year为word模板中的占位符,2021为替换的数据,isMatchCase 是否区分大小写,isMatchWholeWord 是否全词匹配
            doc.getRange().replace(entry.getKey(), entry.getValue(), IS_MATCH_CASE_TRUE, IS_MATCH_WHOLE_WORD_TRUE);
        }
    }

    /**
     * 验证aspose.word组件是否授权:无授权的文件有水印和试用标记
     *
     * @return
     */
    private static boolean isWordLicense() {
        try {
            // 避免文件遗漏
            String licensexml = "<License>\n" + "<Data>\n" + "<Products>\n"
                    + "<Product>Aspose.Total for Java</Product>\n" + "<Product>Aspose.Words for Java</Product>\n"
                    + "</Products>\n" + "<EditionType>Enterprise</EditionType>\n"
                    + "<SubscriptionExpiry>20991231</SubscriptionExpiry>\n"
                    + "<LicenseExpiry>20991231</LicenseExpiry>\n"
                    + "<SerialNumber>23dcc79f-44ec-4a23-be3a-03c1632404e9</SerialNumber>\n" + "</Data>\n"
                    + "<Signature>\n"
                    + "sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=\n"
                    + "</Signature>\n" + "</License>";
            InputStream inputStream = new ByteArrayInputStream(licensexml.getBytes());
            com.aspose.words.License license = new com.aspose.words.License();
            license.setLicense(inputStream);
        } catch (Exception e) {
            System.out.println("License验证异常..." + e);
            return false;
        }
        return true;
    }

    /**
     * 为PDF添加水印
     *
     * @param doc
     * @param waterMarkText
     * @throws Exception
     */
    private static void insertWaterMarkText(Document doc, String waterMarkText) throws Exception {
        Shape watermark = new Shape(doc, ShapeType.TEXT_PLAIN_TEXT);
        // 水印内容
        watermark.getTextPath().setText(waterMarkText);
        // 水印字体
        watermark.getTextPath().setFontFamily("宋体");
        // 水印宽度
        watermark.setWidth(600);
        // 水印高度
        watermark.setHeight(150);
        // 旋转水印
        watermark.setRotation(-60);
        // 水印颜色
        watermark.getFill().setColor(Color.lightGray);
        watermark.setStrokeColor(Color.lightGray);
        watermark.setRelativeHorizontalPosition(RelativeHorizontalPosition.PAGE);
        watermark.setRelativeVerticalPosition(RelativeVerticalPosition.PAGE);
        watermark.setWrapType(WrapType.NONE);
        watermark.setVerticalAlignment(VerticalAlignment.CENTER);
        watermark.setHorizontalAlignment(HorizontalAlignment.CENTER);
        Paragraph watermarkPara = new Paragraph(doc);
        watermarkPara.appendChild(watermark);
        for (Section sect : doc.getSections()) {
            insertWaterMarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_PRIMARY);
            insertWaterMarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_FIRST);
            insertWaterMarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_EVEN);
        }
    }

    private static void insertWaterMarkIntoHeader(Paragraph waterMarkPara, Section sect, int headerType) throws Exception {
        HeaderFooter header = sect.getHeadersFooters().getByHeaderFooterType(headerType);
        if (header == null) {
            header = new HeaderFooter(sect.getDocument(), headerType);
            sect.getHeadersFooters().add(header);
        }
        header.appendChild(waterMarkPara.deepClone(true));
    }
}

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码