根据PDF模版填充数据并生成新的PDF

准备模版

  1. 使用 福昕高级PDF编辑器 (本人用的这个,其他的也行,能作模版就行)
  2. 打开PDF文件点击 表单 选项,点击 文本域
  3. 在需要填充数据的位置设计文本域
  4. 设置 名称、提示
  5. 名称相当于 属性名,提示就是提示,说明这个是什么

导入依赖

        <!--itext-->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.4.2</version>
        </dependency>
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.13</version>
        </dependency>

函数编写

generatePdf

放 ServiceIMpl 里就行,这个是直接浏览器下载生成后的附件

    private final HttpServletResponse response;

    public PdfServiceImpl(HttpServletResponse response) {
        this.response = response;
    }
public void generatePdf(Map<String, String> params) {
        // 读取资源文件夹下的模板
        ClassPathResource resource = new ClassPathResource("pdf-template/文件.pdf");
        InputStream inputStream = resource.getInputStream();

        PdfReader reader = null;
        ByteArrayOutputStream bos = null;
        try {
            reader = new PdfReader(inputStream);
            bos = new ByteArrayOutputStream();
            PdfStamper pdfStamper = new PdfStamper(reader, bos);
            AcroFields acroFields = pdfStamper.getAcroFields();

            // 字体设置
            BaseFont font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);

            for (Map.Entry<String, String> param : params.entrySet()) {
                // 设置文本域的字体为中文字体
                acroFields.setFieldProperty(param.getKey(), "textFont", font, null);
                // 将 map 中的值写到 pdf 模板对应的文本域中
                acroFields.setField(param.getKey(), param.getValue());
            }

            // 如果为false那么生成的PDF文件还能编辑,所以一定要设为true
            pdfStamper.setFormFlattening(true);
            pdfStamper.close();

            // 返回文件
            ServletOutputStream outputStream = response.getOutputStream();
            outputStream.write(bos.toByteArray());
            ServletUtils.writeAttachment(response, "新文件.pdf", bos.toByteArray());
        } catch (IOException | DocumentException e) {
            e.printStackTrace();
        } finally {
            try {
                assert bos != null;
                bos.close();
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

工具类

ServletUtils

import cn.hutool.core.io.IoUtil;
import org.springframework.http.MediaType;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;

/**
 * @Package_Name com.lesliecheung.javacase.util.pdf
 * @Author Leslie Lee
 * @TIME
 * @Version
 */
public class ServletUtils {
    /**
     * 返回附件
     *
     * @param response 响应
     * @param filename 文件名
     * @param content  附件内容
     */
    public static void writeAttachment(HttpServletResponse response, String filename, byte[] content) throws IOException {
        // 设置 header 和 contentType
        response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        // 输出附件
        IoUtil.write(response.getOutputStream(), false, content);
    }
}

获取模版 inputStream

从url下载文件

            // 获取文件地址
            String urlPath = "模板资源文件链接-url";
            // 下载文件
            URL url = new URL(urlPath);
            URLConnection connection = url.openConnection();
            // 设置请求超时时长为 5 秒
            connection.setConnectTimeout(5*1000);
            // 读取数据
            InputStream inputStream = connection.getInputStream();

从某路径下直接取

        String urlPath = "D:\\文件.pdf";
        File file1 = new File(urlPath);
        InputStream inputStream = new FileInputStream(file1);

新文件写入其他位置,操作 bos.toByteArray() 就好了


            File file = new File("D:/新文件.pdf");
            FileOutputStream fos = new FileOutputStream(file);
            BufferedOutputStream boss = new BufferedOutputStream(fos);
            boss.write(bos.toByteArray());

            fos.close();
            boss.close();
            System.out.println("成了");

                                                                Leslie Lee 随笔

可以使用 Apache PDFBox 库来填充 PDF 模板。具体步骤如下: 1. 引入 PDFBox 相关依赖 在 pom.xml 文件中添加以下依赖: ```xml <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.24</version> </dependency> <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox-tools</artifactId> <version>2.0.24</version> </dependency> ``` 2. 准备 PDF 模板文件 使用 Adobe Acrobat 或其他 PDF 编辑器创建一个 PDF 模板文件,其中包含需要填充的表单域。 3. 代码实现 首先,我们需要将 PDF 模板文件读取到 Java 输入流中: ```java InputStream pdfTemplate = this.getClass().getResourceAsStream("/template.pdf"); ``` 然后,我们可以使用 PDFBox 库中的 PDDocument 类来加载模板文件,并获取表单域: ```java PDDocument document = PDDocument.load(pdfTemplate); PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm(); ``` 接下来,我们可以使用表单域的名称来获取表单域,并设置表单域的值: ```java PDTextField field = (PDTextField) acroForm.getField("name"); field.setValue("John Doe"); ``` 最后,我们需要将填充好的 PDF 文件保存到本地或输出到浏览器: ```java document.save("filled.pdf"); document.close(); ``` 完整代码示例: ```java import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm; import org.apache.pdfbox.pdmodel.interactive.form.PDTextField; import java.io.IOException; import java.io.InputStream; public class PdfTemplateFiller { public void fillPdfTemplate() throws IOException { InputStream pdfTemplate = this.getClass().getResourceAsStream("/template.pdf"); PDDocument document = PDDocument.load(pdfTemplate); PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm(); PDTextField field = (PDTextField) acroForm.getField("name"); field.setValue("John Doe"); document.save("filled.pdf"); document.close(); } } ``` 注意,PDFBox 库仅支持填充 PDF 表单域,不支持填充非表单域的 PDF 文件。如果需要在 PDF 文件中添加文本、图像等其他内容,可以考虑使用其他库,如 iText、PDFTron 等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值