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

文章目录

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

前言

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

springboot基础(79):通过pdf模板生成文件_第1张图片
springboot基础(79):通过pdf模板生成文件_第2张图片

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

通过pdf模板生成文件

一 . 制作模板

  1. 先使用wps软件制作一个docx文档
    springboot基础(79):通过pdf模板生成文件_第3张图片

  2. 将文件另存为pdf文件

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

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


springboot基础(79):通过pdf模板生成文件_第4张图片

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

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

  1. 引入依赖
 <dependency>
            <groupId>com.itextpdfgroupId>
            <artifactId>itextpdfartifactId>
            <version>5.5.13.3version>
        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("-------通过模板生成文件结束-------");
    }

springboot基础(79):通过pdf模板生成文件_第5张图片

三、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
    springboot基础(79):通过pdf模板生成文件_第6张图片
  • 下载 访问 http://localhost:8080/pdftest/downloadPdf
    springboot基础(79):通过pdf模板生成文件_第7张图片

预览和下载的区别,只有细微区别。
springboot基础(79):通过pdf模板生成文件_第8张图片

扩展问题

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

遇到的问题

1. 更换字体为宋体常规

springboot基础(79):通过pdf模板生成文件_第9张图片

只能是下面这种写法

//            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);

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

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

点击下载
springboot基础(79):通过pdf模板生成文件_第10张图片

你可能感兴趣的:(前端碎碎练,springboot,spring,boot,pdf,后端)