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. 引入依赖
xml 复制代码
 <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13.3</version>
        </dependency>
  1. 编写pdf工具类和相关工具
java 复制代码
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);
    }

}
java 复制代码
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;
    }
}

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

  1. 测试用例并执行,生成了pdf文件。
java 复制代码
 @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("-------通过模板生成文件结束-------");
    }

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

java 复制代码
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());
    }
}

启动服务器测试

预览和下载的区别,只有细微区别。

扩展问题

android手机浏览器不能在线预览pdf文件,pc浏览器和ios浏览器可以在线预览pdf文件。

解决方案请见: https://lengcz.blog.csdn.net/article/details/132604135

遇到的问题

1. 更换字体为宋体常规

只能是下面这种写法

java 复制代码
//            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);
相关推荐
hlsd#43 分钟前
go mod 依赖管理
开发语言·后端·golang
陈大爷(有低保)1 小时前
三层架构和MVC以及它们的融合
后端·mvc
亦世凡华、1 小时前
【启程Golang之旅】从零开始构建可扩展的微服务架构
开发语言·经验分享·后端·golang
河西石头1 小时前
一步一步从asp.net core mvc中访问asp.net core WebApi
后端·asp.net·mvc·.net core访问api·httpclient的使用
2401_857439691 小时前
SpringBoot框架在资产管理中的应用
java·spring boot·后端
怀旧6661 小时前
spring boot 项目配置https服务
java·spring boot·后端·学习·个人开发·1024程序员节
阿华的代码王国1 小时前
【SpringMVC】——Cookie和Session机制
java·后端·spring·cookie·session·会话
小码编匠2 小时前
领域驱动设计(DDD)要点及C#示例
后端·c#·领域驱动设计
德育处主任Pro2 小时前
『Django』APIView基于类的用法
后端·python·django
哎呦没4 小时前
SpringBoot框架下的资产管理自动化
java·spring boot·后端