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

news2024/11/20 11:50:34

文章目录

  • 前言
  • 通过pdf模板生成文件
    • 一 . 制作模板
    • 二、编辑代码实现模板生成pdf文件
    • 三、pdf在线预览和文件下载
  • 扩展问题
  • 遇到的问题
    • 1. 更换字体为宋体常规

前言

通过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.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13.3</version>
        </dependency>
  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);
    }

}
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文件。
 @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在线预览和文件下载

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());
    }
}

启动服务器测试

  • 预览,访问 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);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/955287.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Docker部署(5)——使用docker run命令部署运行jar项目

对于一些简单的单体项目&#xff0c;可以使用 docker run 命令可以直接在命令行中运行容器&#xff0c;无需事先构建镜像。这相较于之前使用的 dockerfile 文件来运行部署项目相当于是另外一种简单的部署方法&#xff0c;关于之前使用dockerfile 文件来运行部署这种方法&#x…

「MySQL-04」Linux环境下使用C/C++连接并操纵MySQL

目录 一、准备mysql库&#xff1a;Connector/C 1. 查看是否有mysql相关的库和头文件 2. 安装devel(开发库) 3.到官网下载开发包&#xff0c;并上传到Linux 3.0 须知 3.1 到官网下载开发包 3.2 上传安装包至Linux 二、mysql库&#xff1a;Connector/C 的使用 1. 创建并初始化mys…

DataLoader的使用

示例代码&#xff1a; import torchvision from torch.utils.data import DataLoader from torch.utils.tensorboard import SummaryWriter# 准备的测试数据集 test_data torchvision.datasets.CIFAR10("./dataset", trainFalse, transformtorchvision.transforms.…

react里map嵌套

1、tab是我自己声明的变量&#xff0c;item是下标&#xff0c;index是key值&#xff08;这些都可以改为自己的数据&#xff09; tab是声明的所有数据&#xff0c;而list是所有数据里面所需要的那一个&#xff0c;items和indexs可以虽然写一个名称代替

HTML基础--Form表单--内联元素

目录 Form表单 表单元素 创建表单 () 文本输入 () 密码输入 单选按钮 () 和 复选框 () 下拉列表 () 和 选项 ()提交按钮 () 重置按钮 () 块元素与行内元素&#xff08;内联元素&#xff09; Form表单 HTML中的表单&#xff08;<form>&#xff09;是一个重要的元…

WPF C# .NET7 基础学习

学习视频地址&#xff1a;https://www.bilibili.com/video/BV1hx4y1G7C6?p3&vd_source986db470823ebc16fe0b3d235addf050 开发工具&#xff1a;Visual Studio 2022 Community 基础框架&#xff1a;.Net 6.0 下载创建过程略 .Net和.Framework 区别是Net是依赖项&#xff…

EasyAVFilter的初衷:把ffmpeg.c当做SDK来用,而不是当做EXE来用

之前我们做一个视频点播的功能&#xff0c;大概的流程就是将上传上来的各种格式的视频&#xff0c;用FFmpeg统一进行一次转码&#xff0c;如果probe到视频的编码格式是H.264就调用-vcodec copy&#xff0c;如果probe到视频的编码格式不是H.264就调用-vcodec libx264&#xff0c…

SpringBoot中自定义starter

SpringBoot自动装配原理&#xff1a; EnableAutoConfiguration注解开启自动装配功能&#xff0c;该注解通常放在应用的主类上。spring.factories文件位于META-INF目录下的配置文件中定义各个自动装配类的全限定名 当SpringBoot启动时&#xff0c;会加载classpath下所有的spri…

JavaScript 手写题

基础手写 全排列&#xff08;力扣原题&#xff09; 要求以数组的形式返回字符串参数的所有排列组合。 注意&#xff1a; 字符串参数中的字符无重复且仅包含小写字母返回的排列组合数组不区分顺序const _permute string > {const result []const map new Map()const df…

vue使用打印组件print-js

项目场景&#xff1a; 由于甲方要求&#xff0c;项目需要打印二维码标签&#xff0c;故开发此功能 开发流程 安装包&#xff1a;npm install print-js --saveprint-js的使用 <template><div id"print" ref"print" ><p>打印内容<p&…

可拖拽编辑的流程图X6

先上图 //index.html&#xff0c;有时候可能加载失败&#xff0c;那就再找一个别的cdn 或者npm下载&#xff0c;如果npm下载&#xff0c; //那么需要全局引入或者局部引入&#xff0c;代码里面写法也会不同&#xff0c;详细的可以看示例<script src"https://cdn.jsdeli…

python可视化——pycharm——Grid - Grid_overlap_multi_xy_axis图

这段代码使用了pyecharts库来创建一个Grid-Overlap图&#xff0c;包括柱状图和折线图。 首先&#xff0c;创建了一个柱状图对象bar&#xff0c;并添加了两个y轴的数据。第一个y轴代表csdn博客数量&#xff0c;第二个y轴代表粉丝数量。然后&#xff0c;使用extend_axis方法扩展…

6、深入解析Kotlin类与对象:构造、伴生、单例全面剖析

前言 本篇文章将带您了解Kotlin编程中的重要概念&#xff1a;类及构造函数、访问修饰符、伴生对象和单例模式。就像搭积木一样&#xff0c;我们会逐步揭开这些概念的面纱&#xff0c;让您轻松理解它们的作用和用法。无论您是编程新手还是有经验的开发者&#xff0c;本文都将为…

一个独立的测试人如何完成一个项目的测试 + 发布

其实啊&#xff0c;每个人都可以「独立完成一个项目的测试 发布」 很多同学&#xff0c;工作了五六年&#xff0c;都没有机会&#xff08;也许是&#xff1a;不敢&#xff09;独立负责一个完整项目的测试&#xff08;独立负责一个项目测试后的上线流程&#xff0c;机会就更少…

手把手教你调用5个公共API获取数字货币市场数据(内附详细源码)

数量技术宅团队在CSDN学院推出了量化投资系列课程 欢迎有兴趣系统学习量化投资的同学&#xff0c;点击下方链接报名&#xff1a; 量化投资速成营&#xff08;入门课程&#xff09; Python股票量化投资 Python期货量化投资 Python数字货币量化投资 C语言CTP期货交易系统开…

three.js(十):线性几何体

线性几何体 WireframeGeometry 网格几何体EdgesGeometry 边缘几何体 WireframeGeometry 网格几何体 WireframeGeometry( geometry : BufferGeometry ) geometry — 任意几何体对象。 const geometry new SphereGeometry(); const wireframe new WireframeGeometry(geometr…

2022年06月 C/C++(五级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题&#xff1a;逃离迷宫 你在一个地下迷宫中找到了宝藏&#xff0c;但是也触发了迷宫机关&#xff0c;导致迷宫将在T分钟后坍塌&#xff0c;为此你需要在T分钟内逃离迷宫&#xff0c;你想知道你能不能逃离迷宫。迷宫是一个边长为m的正方形&#xff0c;其中"S"表示…

完善会计流程的关键功能:了解必备的会计软件功能!

会计软件已经成为许多大小企业的财务管理标配。会计软件可以帮助企业自动化财务流程&#xff0c;提高工作效率&#xff0c;减少错误&#xff0c;并提供准确和可靠的财务数据。一款合格的会计软件应该具备什么功能呢&#xff1f; 会计软件应有的功能 1、账户管理&#xff1a;会…

overlayfs

参考&#xff1a;How containers work: overlayfs how overlays work Overlay filesystems, also known as “union filesystems” or “union mounts” let you mount a filesystem using 2 directories: a “lower” directory, and an “upper” directory. Basically: t…