• springboot基础(79):通过pdf模板生成文件


    前言

    通过pdf模板生成文件。
    支持文本,图片,勾选框。

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

    本章代码已分享至Gitee: https://gitee.com/lengcz/pdfdemo01

    通过pdf模板生成文件

    一 . 制作模板

    1. 先使用wps软件制作一个docx文档
      在这里插入图片描述

    2. 将文件另存为pdf文件
      在这里插入图片描述

    3. 使用pdf编辑器,编辑表单,(例如福昕PDF阅读器、Adobe Acrobat DC)

    不同的pdf编辑器使用方式不同,建议自行学习如何使用pdf编辑器编辑表单

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

    1. 将修改后的文件保存为template1.pdf文件。

    二、编辑代码实现模板生成pdf文件

    1. 引入依赖
     <dependency>
                <groupId>com.itextpdfgroupId>
                <artifactId>itextpdfartifactId>
                <version>5.5.13.3version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 编写pdf工具类和相关工具
    package com.it2.pdfdemo01.util;
    
    import com.itextpdf.text.BadElementException;
    import com.itextpdf.text.DocumentException;
    import com.itextpdf.text.Image;
    import com.itextpdf.text.Rectangle;
    import com.itextpdf.text.pdf.*;
    
    import java.io.*;
    import java.util.List;
    import java.util.Map;
    
    /**
     * pdf 工具
     */
    public class PdfUtil {
    
    
        /**
         * 通过pdf模板输出到流
         *
         * @param templateFile 模板
         * @param dataMap      input数据
         * @param picData      image图片
         * @param checkboxMap  checkbox勾选框
         * @param outputStream 输出流
         */
        public static void output(String templateFile, Map<String, Object> dataMap, Map<String, byte[]> picData, Map<String, String> checkboxMap, OutputStream outputStream) {
            OutputStream os = null;
            PdfStamper ps = null;
            PdfReader reader = null;
    
            try {
                reader = new PdfReader(templateFile);
                ps = new PdfStamper(reader, outputStream);
                AcroFields form = ps.getAcroFields();
                BaseFont bf = BaseFont.createFont("Font/SIMYOU.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
                form.addSubstitutionFont(bf);
                if (null != dataMap) {
                    for (String key : dataMap.keySet()) {
                        form.setField(key, dataMap.get(key).toString());
                    }
                }
                ps.setFormFlattening(true);
                if (null != checkboxMap) {
                    for (String key : checkboxMap.keySet()) {
                        form.setField(key, checkboxMap.get(key), true);
                    }
                }
    
                PdfStamper stamper = ps;
                if (null != picData) {
                    picData.forEach((filedName, imgSrc) -> {
                        List<AcroFields.FieldPosition> fieldPositions = form.getFieldPositions(filedName);
                        for (AcroFields.FieldPosition fieldPosition : fieldPositions) {
                            int pageno = fieldPosition.page;
                            Rectangle signrect = fieldPosition.position;
                            float x = signrect.getLeft();
                            float y = signrect.getBottom();
                            byte[] byteArray = imgSrc;
                            try {
                                Image image = Image.getInstance(byteArray);
                                PdfContentByte under = stamper.getOverContent(pageno);
                                image.scaleToFit(signrect.getWidth(), signrect.getHeight());
                                image.setAbsolutePosition(x, y);
                                under.addImage(image);
                            } catch (BadElementException e) {
                                e.printStackTrace();
                            } catch (IOException e) {
                                e.printStackTrace();
                            } catch (DocumentException e) {
                                e.printStackTrace();
                            }
                        }
                    });
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    ps.close();
                    reader.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    
    
        /**
         * 通过pdf模板输出到文件
         *
         * @param templateFile 模板
         * @param dataMap      input数据
         * @param picData      image图片
         * @param checkboxMap  checkbox勾选框
         * @param outputFile   输出流
         */
        public static void output(String templateFile, Map<String, Object> dataMap, Map<String, byte[]> picData, Map<String, String> checkboxMap, File outputFile) throws IOException {
            FileOutputStream fos = new FileOutputStream(outputFile);
            try {
                output(templateFile, dataMap, picData, checkboxMap, fos);
            } finally {
                fos.close();
            }
        }
    
        /**
         * 通过pdf模板输出到文件
         *
         * @param templateFile 模板
         * @param dataMap      input数据
         * @param picData      image图片
         * @param checkboxMap  checkbox勾选框
         * @param filePath     路径
         * @param fileName     文件名
         */
        public static void output(String templateFile, Map<String, Object> dataMap, Map<String, byte[]> picData, Map<String, String> checkboxMap, String filePath, String fileName) throws IOException {
            File file = new File(filePath + File.separator + fileName);
            output(templateFile, dataMap, picData, checkboxMap, file);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    package com.it2.pdfdemo01.util;
    
    import javax.imageio.ImageIO;
    import java.awt.image.BufferedImage;
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.IOException;
    
    /**
     * 图片工具
     */
    public class ImageUtil {
    
        /**
         * 通过图片路径获取byte数组
         *
         * @param url 路径
         * @return
         */
        public static byte[] imageToBytes(String url) {
            ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
            BufferedImage bufferedImage = null;
            try {
                bufferedImage = ImageIO.read(new File(url));
                ImageIO.write(bufferedImage, "jpg", byteOutput);
                return byteOutput.toByteArray();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (byteOutput != null)
                        byteOutput.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return null;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    用到的字体文件(幼圆常规,C盘Windows/Fonts目录下

    在这里插入图片描述

    1. 测试用例并执行,生成了pdf文件。
     @Test
        public void testPdf() throws IOException {
            String templateFile = "D:\\test3\\template1.pdf";
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put("username", "王小鱼");
            dataMap.put("age", "11");
            dataMap.put("address", "深圳市宝安区和林大道");
    
            Map<String, byte[]> picMap = new HashMap<>();
            byte[] imageToBytes = ImageUtil.imageToBytes("D:\\test3\\dog3.png");
            picMap.put("head", imageToBytes);
    
            Map<String, String> checkboxMap = new HashMap<>();
            checkboxMap.put("apple", "Yes");
            checkboxMap.put("orange", "Yes");
            checkboxMap.put("peach", "No");
    
            PdfUtil.output(templateFile, dataMap, picMap, checkboxMap, "D:\\test3", "test1.pdf");
            System.out.println("-------通过模板生成文件结束-------");
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述

    三、pdf在线预览和文件下载

    package com.it2.pdfdemo01.controller;
    
    import com.it2.pdfdemo01.util.ImageUtil;
    import com.it2.pdfdemo01.util.PdfUtil;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    
    
    @RestController
    @RequestMapping("/pdftest")
    public class MyPdfController {
    
        /**
         * 在线预览pdf
         *
         * @param request
         * @param response
         * @throws IOException
         */
        @GetMapping("/previewPdf")
        public void previewPdf(HttpServletRequest request, HttpServletResponse response) throws IOException {
            String templateFile = "D:\\test3\\template1.pdf";
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put("username", "王小鱼");
            dataMap.put("age", "11");
            dataMap.put("address", "深圳市宝安区和林大道");
    
            Map<String, byte[]> picMap = new HashMap<>();
            byte[] imageToBytes = ImageUtil.imageToBytes("D:\\test3\\dog3.png");
            picMap.put("head", imageToBytes);
    
            Map<String, String> checkboxMap = new HashMap<>();
            checkboxMap.put("apple", "Yes");
            checkboxMap.put("orange", "Yes");
            checkboxMap.put("peach", "No");
    
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/pdf");
            String fileName = new String("测试预览pdf文件".getBytes(), "ISO-8859-1");//避免中文乱码
            response.setHeader("Content-Disposition", "inline;filename=".concat(String.valueOf(fileName) + ".pdf"));
            PdfUtil.output(templateFile, dataMap, picMap, checkboxMap, response.getOutputStream());
        }
    
        /**
         * 下载pdf
         *
         * @param request
         * @param response
         * @throws IOException
         */
        @GetMapping("/downloadPdf")
        public void downloadPdf(HttpServletRequest request, HttpServletResponse response) throws IOException {
            String templateFile = "D:\\test3\\template1.pdf";
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put("username", "王小鱼");
            dataMap.put("age", "11");
            dataMap.put("address", "深圳市宝安区和林大道");
    
            Map<String, byte[]> picMap = new HashMap<>();
            byte[] imageToBytes = ImageUtil.imageToBytes("D:\\test3\\dog3.png");
            picMap.put("head", imageToBytes);
    
            Map<String, String> checkboxMap = new HashMap<>();
            checkboxMap.put("apple", "Yes");
            checkboxMap.put("orange", "Yes");
            checkboxMap.put("peach", "No");
    
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/pdf");
            String fileName = new String("测试预览pdf文件".getBytes(), "ISO-8859-1");//避免中文乱码
            response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(fileName) + ".pdf"));
            PdfUtil.output(templateFile, dataMap, picMap, checkboxMap, response.getOutputStream());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81

    启动服务器测试

    • 预览,访问 http://localhost:8080/pdftest/previewPdf
      在这里插入图片描述
    • 下载 访问 http://localhost:8080/pdftest/downloadPdf
      在这里插入图片描述

    预览和下载的区别,只有细微区别。
    在这里插入图片描述

    扩展问题

    android手机浏览器不能在线预览pdf文件,pc浏览器和ios浏览器可以在线预览pdf文件。
    解决方案请见: https://lengcz.blog.csdn.net/article/details/132604135

    遇到的问题

    1. 更换字体为宋体常规

    在这里插入图片描述

    只能是下面这种写法

    //            BaseFont bf = BaseFont.createFont("Font/SIMYOU.TTF", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); //幼圆常规
                String srcFilePath = PdfUtil.class.getResource("/")+ "Font/simsun.ttc"; //宋体常规
                String templatePath = srcFilePath.substring("file:/".length())+",0";
                BaseFont bf = BaseFont.createFont(templatePath, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2. 下载时中文文件名乱码问题

    String fileName = new String("测试预览pdf文件".getBytes(), "ISO-8859-1");//避免中文乱码
            response.setHeader("Content-Disposition", "attachment;filename=".concat(String.valueOf(fileName) + ".pdf"));
    
    • 1
    • 2

    或者

     String fileName = URLEncoder.encode("测试文件", "UTF-8");//避免中文乱码
     response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".pdf");
    
    • 1
    • 2

    点击下载
    在这里插入图片描述

    传送门

    pdf添加水印

  • 相关阅读:
    小学妹刚毕业没地方住想来借宿?于是我连夜用Python给她找了个好房子,我真是太机智了
    服务端渲染和客户端渲染的区别
    uni-app----图片点击放大功能&&点击文本进行复制功能【安卓app端】
    【ESP-BOX-LITE】:照片查看器
    算法技巧-二叉树
    中国顶级CTF竞赛网络安全大赛--2022网鼎杯re2解题思路来了,快来围观!
    Visual Studio:Entity设置表之间的关联关系
    基于STM32设计的智能家居控制系统设计_语音+环境检测(OneNet)_2022
    Kibana忘记初始密码怎么办?
    golang单元测试:testing包的基本使用
  • 原文地址:https://blog.csdn.net/u011628753/article/details/132611718