Java PDF工具类(一)| 使用 itextpdf 填充PDF模板(文字和图片)


Java PDF工具类(一)| 使用 itextpdf 填充PDF模板(文字和图片)


相关文章: Java PDF工具类(二)| 使用 wkhtmltox 实现 HTML转PDF(文字/图片/页眉页脚).

参考文章:https://www.cnblogs.com/wangpeng00700/p/8418594.html


这里主要使用到 itextpdf 的工具包
特点:

  • 一对一,点对点的给对应的地方写值,比如模板里面放了个name标识,在程序里把“张三”赋给name,那么输出的pdf里面name的地方就变成了张三,准确方便快捷
  • 支持中文,可以使用自己下载的字体。
  • 支持图片:图片的大小范围可以在模板随意调,生成出来的图片不会超过范围。而且不需要根据坐标去算,程序里面自动计算的。
  • 支持多页模板,即使是好几页的模板,只要每个变量对应的范围确定好了,生成出来的格式就不会错乱。

这里我下载了一个宋体的字体文件,大家可以下载进行参考(也可以使用不用字体文件的,后面看代码):

  • 链接:https://pan.baidu.com/s/13i4t7R4gHOBUeh4lGzVZYg
  • 提取码:s7un

效果图:
在这里插入图片描述


一、模板准备
1.下载编辑PDF软件(adobe_acrobat_pro),大家可自行下载,也可关注公众号:慌途L,回复:​PDF编辑软件,即可拿到下载链接

在这里插入图片描述

下载成功,解压后双击运行安装:
在这里插入图片描述


2.根据work模板生成对应的PDF模板文件

1.新建一个work文档,并将其另存为为PDF格式:

在这里插入图片描述
在这里插入图片描述

2.将名称为 test2 的PDF文件用第一步安装的 Adobe Acrobat Pro 打开,进行表单的编辑和变量名的填充:
在这里插入图片描述

设置文本域的变量名,后期在代码中用于替换对应的值用:
在这里插入图片描述

也可以设置字体大小等,是否需要边框
在这里插入图片描述

设置图片,图片的地方没有文本域,在空白地方点击右键,选择文本域,然后就可以规定显示图片区域的大小了,最后的图片显示不会超出这个边框:
在这里插入图片描述
在这里插入图片描述

最后的结果,直接保存即可:
在这里插入图片描述


二、具体代码实现

1.在pom文件中引入 itextpdf 依赖

<!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.13</version>
</dependency>
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext-asian</artifactId>
    <version>5.2.0</version>
</dependency>

2.在F盘下放入test2.pdf文件和一张图片
在这里插入图片描述


3.PDFUtils:

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * PDF生成
 */
public class PDFUtil {
    /** 模板路径 */
    private static final String TEMPLATE_PATH = "F:\\test2.pdf";

    /** 生成的新文件路径 */
    private static final String NEW_PDF_PATH = "F:\\testOut1.pdf";

	/**
     * 判断当前系统是否是Windows系统
     * @return true:Windows系统,false:Linux系统
     */
    public static boolean isWindowsSystem(){
        String property = System.getProperty("os.name").toLowerCase();
        return property.contains("windows");
    }

    /**
     * 填充PDF模板
     * @param sourceMap 数据源Map
     */
    public static void fillPDFTemplate(Map<String,Object> sourceMap) {
        PdfReader reader = null;
        FileOutputStream out = null;
        ByteArrayOutputStream bos = null;
        PdfStamper stamper;
        try {
            // 设置字体,解决中文问题1(推荐用第二种,不需要依赖字体文件)
            // BaseFont bf = BaseFont.createFont("D:\\bb2360\\simsun.ttf" , BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            // 解决中文问题2
            BaseFont bfChinese;
            if(isWindowsSystem()){
                bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
            } else {
            	// 这里将simsun.ttf文件放在项目的resources/font下,也可以直接放到liunx上
                bfChinese = BaseFont.createFont("font/simsun.ttf" , BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            }
            Font fontText = new Font(bfChinese, 8, Font.NORMAL);

            // 暂时没找到在哪里放入
            // Font fontChinese = new Font(bf, 3, Font.NORMAL);
            // Font font = new Font(bf, 32);
            out = new FileOutputStream(NEW_PDF_PATH);// 输出流
            reader = new PdfReader(TEMPLATE_PATH);// 读取pdf模板
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);
            AcroFields form = stamper.getAcroFields();

            //文字类的内容处理
            Map<String, String> dataMap = (Map<String,String>) sourceMap.get("dataMap");
            form.addSubstitutionFont(bfChinese);
            for(String key : dataMap.keySet()){
                String value = dataMap.get(key);
                form.setField(key, value);
            }

            //图片类的内容处理
            Map<String, Object> imageMap = (Map<String,Object>) sourceMap.get("imageMap");
            for(String key : imageMap.keySet()) {
                String imgpath = imageMap.get(key).toString();
                int pageNo = form.getFieldPositions(key).get(0).page;
                Rectangle signRect = form.getFieldPositions(key).get(0).position;
                float x = signRect.getLeft();
                float y = signRect.getBottom();
                //根据路径读取图片
                Image image = Image.getInstance(imgpath);
                //获取图片页面
                PdfContentByte under = stamper.getOverContent(pageNo);
                //图片大小自适应
                image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                //添加图片
                image.setAbsolutePosition(x, y);
                under.addImage(image);
            }
            stamper.setFormFlattening(true);// 如果为false,生成的PDF文件可以编辑,如果为true,生成的PDF文件不可以编辑
            stamper.close();

            // 生成文件
            Document doc = new Document();
            PdfCopy copy = new PdfCopy(doc, out);
            doc.open();
            PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
            copy.addPage(importPage);
            doc.close();

            // 比上面生成的文件会大一点
//            FileCopyUtils.copy(bos.toByteArray(), new FileOutputStream("D:\\test\\testOut2.pdf"));
        } catch (IOException | DocumentException e) {
            System.out.println("填充PDF异常.....");
            System.out.println(e);
        } finally {
            try {
                if(out != null){
                    out.close();
                }
                if(reader != null){
                    reader.close();
                }
                if(bos != null){
                    bos.close();
                }
            } catch (IOException e){
                e.printStackTrace();
            }
        }
    }

    /**
     * 填充PDF模板并返回字节流
     * @param sourceMap     数据源Map
     * @param inputStream   PDF文件的字节流
     * @return  返回填充好的PDF文件字节流
     */
    public static byte[] fillPDFTemplate(Map<String,Object> sourceMap, ByteArrayInputStream inputStream) {
        PdfReader reader = null;
        ByteArrayOutputStream bos = null;
        PdfStamper stamper;
        try {
            // 解决中文问题2
            BaseFont bfChinese;
            if(isWindowsSystem()){
                bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
            } else {
            	// 这里将simsun.ttf文件放在项目的resources/font下,也可以直接放到liunx上
                bfChinese = BaseFont.createFont("font/simsun.ttf" , BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            }
            Font fontText = new Font(bfChinese, 8, Font.NORMAL);

            reader = new PdfReader(inputStream);// 读取pdf模板
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);
            AcroFields form = stamper.getAcroFields();

            //文字类的内容处理
            Map<String, String> dataMap = (Map<String,String>) sourceMap.get("dataMap");
            form.addSubstitutionFont(bfChinese);
            for(String key : dataMap.keySet()){
                String value = dataMap.get(key);
                form.setField(key, value);
            }

            //图片类的内容处理
            Map<String, Object> imageMap = (Map<String,Object>) sourceMap.get("imageMap");
            for(String key : imageMap.keySet()) {
                String imgpath = imageMap.get(key).toString();
                int pageNo = form.getFieldPositions(key).get(0).page;
                Rectangle signRect = form.getFieldPositions(key).get(0).position;
                float x = signRect.getLeft();
                float y = signRect.getBottom();
                //根据路径读取图片
                Image image = Image.getInstance(imgpath);
                //获取图片页面
                PdfContentByte under = stamper.getOverContent(pageNo);
                //图片大小自适应
                image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                //添加图片
                image.setAbsolutePosition(x, y);
                under.addImage(image);
            }
            stamper.setFormFlattening(true);// 如果为false,生成的PDF文件可以编辑,如果为true,生成的PDF文件不可以编辑
            stamper.close();

            // 返回填充好的PDF文件字节流
            return bos.toByteArray();
        } catch (IOException | DocumentException e) {
            System.out.println("填充PDF异常.....");
            System.out.println(e);
            return null;
        } finally {
            try {
                if(reader != null){
                    reader.close();
                }
                if(bos != null){
                    bos.close();
                }
            } catch (IOException e){
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        Map<String,Object> map = new HashMap<>();
        map.put("name","张三");
        map.put("idcard","430159189802156596");

        Map<String,Object> map2 = new HashMap<>();
        map2.put("image","F:\\test2.png");

        Map<String,Object> formMap = new HashMap<>();
        formMap.put("dataMap",map);
        formMap.put("imageMap",map2);
        fillPDFTemplate(formMap);
    }
}

4.结果展示:
在这里插入图片描述


至此结束,更多的功能和优化,大家可以自行补充完整!希望能对大家有用!

注意:如果在Liunx上生成PDF后出现中文不显示,可参考以下方案
  • 1.可将simsun.ttf字体文件放入/usr/share/fonts/目前下

  • 2.如代码里一样,将字体文件/usr/share/fonts/放入到项目中或者Liunx服务器上,指定文件路径即可

相关文章: Java PDF工具类(二)| 使用 wkhtmltox 实现 HTML转PDF(文字/图片/页眉页脚).

欢迎关注公众号:慌途L
后面会慢慢将文章迁移至公众号,也是方便在没有电脑的情况下可以进行翻阅,更新的话会两边同时更新,大家不用担心!
在这里插入图片描述


  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
使用iTextPDF生成pdf填充自定义数据的步骤如下: 1. 首先,获取需要生成pdf的初始模板,包含格式,但不包含数据。可以使用工具如Adobe Acrobat来编辑pdf模板,在对应区域生成文本域,为每个域设置一个唯一的名称。 2. 在Java代码中,使用iTextPDF库来对pdf进行操作。首先,需要获取PdfReader对象,将模板文件加载为PdfReader对象。可以使用以下代码: ```java PdfReader reader = new PdfReader(templatePath); // templatePath是模板pdf文件的路径 ``` 3. 接下来,使用PdfStamper对象来填充数据并生成最终的pdf文件。可以使用以下代码: ```java PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(outputPath)); // outputPath是生成的pdf文件的路径 AcroFields fields = stamper.getAcroFields(); // 使用fields对象来填充文本域的数据 fields.setField("fieldName1", "fieldValue1"); fields.setField("fieldName2", "fieldValue2"); // 继续填充其他文本域的数据 // 最后,调用stamper的close方法来保存并关闭pdf文件 stamper.close(); ``` 4. 通过上述步骤,你可以使用iTextPDF将自定义数据填充pdf模板中,并生成最终的pdf文件。 请注意,以上代码只展示了主要的方法代码,并不是整个流程的逻辑代码。具体的实现可能会根据具体的需求和模板结构有所不同。 <span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [java使用itextpdf生成pdf填充自定义数据](https://blog.csdn.net/qq_34244426/article/details/104833805)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值