美文网首页
java springboot 生成pdf 亲测可用 附源码

java springboot 生成pdf 亲测可用 附源码

作者: 程序之道 | 来源:发表于2020-09-23 15:58 被阅读0次

    实验时间: 2020-09-23
    代码: https://github.com/mefly521/springbootAllinone spring-boot-pdf-template模块

    本文介绍将一个制作好的模板自动填充上动态内容的方法.
    网上有好多方法没有一一实验,因为有些不能跨平台,有些需要装dll 或其它第三方组件所以将其排除.

    只介绍我实验成功的2种方法 :
    方法1生成速度比较快,但需要下载 Adobe Acrobat dc 编辑模板,
    方法2 为word 模板,先将word模板的动态内容填充后,再将word 转成 pdf.缺点是速度比较慢,将近10秒

    1 pdf模板生成

    下载 Adobe Acrobat dc
    http://www.downza.cn/soft/20562.html

    用dc 打开pdf , 编写静态文字


    image.png

    再点准备表单
    将文本框放上去, 将编辑名称, 名称是后面用于替换的key


    image.png

    引用的包

    <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>3.11</version>
            </dependency>
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>2.8.0</version>
            </dependency>
    
            <!-- itextpdf 依赖包 -->
            <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>
    

    代码

    package com.demo.controller;
    
    import com.itextpdf.text.Document;
    import com.itextpdf.text.pdf.*;
    import org.apache.commons.io.FileUtils;
    import org.apache.commons.io.IOUtils;
    import org.apache.commons.lang3.StringUtils;
    import java.io.*;
    import java.util.*;
    
    /**
     * 生成pdf的工具类
     */
    public class PdfUtils
    {
        public static void main(String[] args) throws IOException
        {
            //Map中Key对应PDF表单中的fieldNames,Value则是你想填充的值
            HashMap map = new HashMap<String, String>();
            map.put("number","2020");
            map.put("sex","On");    //Value为On 则勾选这个复选框
            map.put("test","On");   //Value为On 则勾选这个复选框
            map.put("fill_1","被检查单位123232");
            map.put("fill_18","有一小鸟,它的家搭在最高的树枝上,它的羽毛还未丰满,不能要飞,每日只在家里叽叽地叫着,和两只老鸟说着话儿,他们都是觉得非常的快乐。这一天早晨,它醒了,那两个老鸟都找食物去了。一看见火红的太阳,它们又害怕了,因为太阳太大了,它们又看见一棵树上的一片好大的树叶,树叶上又有站着一只小鸟,正在吃害虫,害虫吃了很多树叶,让大树不能长大,大树是我们的好朋友,每一棵树都产生氧气,让我们每一个人呼吸。这时老鸟马上飞过去,与小鸟一起吃害虫,吃得饱饱的,并为民除害。");
            String sourceFile = "D:\\temp\\01\\p22.pdf"; //原文件路径
            String targetFile = "D:\\temp\\01\\output.pdf";     //目标文件路径
            PdfUtils.genPdf(map,sourceFile,targetFile);
        }
    
        /**
         * @param map 需要填充的字段
         * @param sourceFile  原文件路径
         * @param targetFile  目标文件路径
         * @throws IOException
         */
        public static void genPdf(HashMap map, String sourceFile, String targetFile) throws IOException {
            File templateFile = new File(sourceFile);
            fillParam(map, FileUtils.readFileToByteArray(templateFile), targetFile);
        }
    
        /**
         * Description: 使用map中的参数填充pdf,map中的key和pdf表单中的field对应 <br>
         * @author mk
         * @Date 2018-11-2 15:21 <br>
         * @Param
         * @return
         */
        public static void fillParam(Map<String, String> fieldValueMap, byte[] file, String contractFileName) {
            FileOutputStream fos = null;
            try {
    
                fos = new FileOutputStream(contractFileName);
                PdfReader reader = null;
                PdfStamper stamper = null;
                BaseFont base = null;
                try {
                    reader = new PdfReader(file);
                    stamper = new PdfStamper(reader, fos);
                    stamper.setFormFlattening(true);
                    base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); //简体中文字体
                    //base = BaseFont.createFont("MHei-Medium", "UniCNS-UCS2-H", BaseFont.NOT_EMBEDDED);  //繁体中文字体
                    AcroFields acroFields = stamper.getAcroFields();
                    for (String key : acroFields.getFields().keySet()) {
                        acroFields.setFieldProperty(key, "textfont", base, null);
                        acroFields.setFieldProperty(key, "textsize", new Float(9), null);   //字体大小
                    }
                    if (fieldValueMap != null) {
                        for (String fieldName : fieldValueMap.keySet())
                        {
                            if (StringUtils.isNotBlank(fieldValueMap.get(fieldName)))
                            {
                                //获取map中key对应的Value是否为On,若是则勾选复选框
                                if (fieldValueMap.get(fieldName).equals("On") || fieldValueMap.get(fieldName) == "On")
                                {
                                    acroFields.setField(fieldName, fieldValueMap.get(fieldName),true);
                                }else
                                {
                                    acroFields.setField(fieldName, fieldValueMap.get(fieldName));
                                }
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (stamper != null) {
                        try {
                            stamper.close();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    if (reader != null) {
                        reader.close();
                    }
                }
    
            } catch (Exception e) {
                System.out.println("填充参数异常");
                e.printStackTrace();
            } finally {
                IOUtils.closeQuietly(fos);
            }
        }
    
    
        /**
         * Description: 获取pdf表单中的fieldNames<br>
         * @author mk
         * @Date 2018-11-2 15:21 <br>
         * @Param
         * @return
         */
        public static Set<String> getTemplateFileFieldNames(String pdfFileName) {
            Set<String> fieldNames = new TreeSet<String>();
            PdfReader reader = null;
            try {
                reader = new PdfReader(pdfFileName);
                Set<String> keys = reader.getAcroFields().getFields().keySet();
                for (String key : keys) {
                    int lastIndexOf = key.lastIndexOf(".");
                    int lastIndexOf2 = key.lastIndexOf("[");
                    fieldNames.add(key.substring(lastIndexOf != -1 ? lastIndexOf + 1 : 0, lastIndexOf2 != -1 ? lastIndexOf2 : key.length()));
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (reader != null) {
                    reader.close();
                }
            }
    
            return fieldNames;
        }
    
    
        /**
         * Description: 读取文件数组<br>
         * @author mk
         * @Date 2018-11-2 15:21 <br>
         * @Param
         * @return
         */
        public static byte[] fileBuff(String filePath) throws IOException {
            File file = new File(filePath);
            long fileSize = file.length();
            if (fileSize > Integer.MAX_VALUE) {
                //System.out.println("file too big...");
                return null;
            }
            FileInputStream fi = new FileInputStream(file);
            byte[] file_buff = new byte[(int) fileSize];
            int offset = 0;
            int numRead = 0;
            while (offset < file_buff.length && (numRead = fi.read(file_buff, offset, file_buff.length - offset)) >= 0) {
                offset += numRead;
            }
            // 确保所有数据均被读取
            if (offset != file_buff.length) {
                throw new IOException("Could not completely read file " + file.getName());
            }
            fi.close();
            return file_buff;
        }
    
        /**
         * Description: 合并pdf <br>
         * @author mk
         * @Date 2018-11-2 15:21 <br>
         * @Param
         * @return
         */
        public static void mergePdfFiles(String[] files, String savepath) {
            Document document = null;
            try {
                document = new Document(); //默认A4大小
                PdfCopy copy = new PdfCopy(document, new FileOutputStream(savepath));
                document.open();
                for (int i = 0; i < files.length; i++) {
                    PdfReader reader = null;
                    try {
                        reader = new PdfReader(files[i]);
                        int n = reader.getNumberOfPages();
                        for (int j = 1; j <= n; j++) {
                            document.newPage();
                            PdfImportedPage page = copy.getImportedPage(reader, j);
                            copy.addPage(page);
                        }
                    } finally {
                        if (reader != null) {
                            reader.close();
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                //关闭PDF文档流,OutputStream文件输出流也将在PDF文档流关闭方法内部关闭
                if (document != null) {
                    document.close();
                }
    
            }
        }
    }
    
    
    

    2 先成word 再转成pdf

    制作一个word 模板再使用 poi-tl (http://deepoove.com/poi-tl/)这个组件填充内容
    再将word 转成pdf (具体看这篇文章 https://blog.csdn.net/hunwanjie/article/details/97135633,亲测可用)
    但是测试后发现转换时间比较长, 用了将近10秒,考虑到性能问题,暂时将第2种设为备选.
    优先使用第一种,除非找不到编辑pdf 的软件 .

    Java使用itext 根据PDF模板进行填充并生成_weixin_43910274的博客-CSDN博客
    https://blog.csdn.net/weixin_43910274/article/details/104916106?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

    相关文章

      网友评论

          本文标题:java springboot 生成pdf 亲测可用 附源码

          本文链接:https://www.haomeiwen.com/subject/knznyktx.html