首页 > 其他分享 >根据PDF模板生成具体内容PDF,模板pdf需要设置字段域

根据PDF模板生成具体内容PDF,模板pdf需要设置字段域

时间:2023-05-03 10:23:59浏览次数:32  
标签:段域 fields bos param new PDF null data 模板

package com.zudp.common.core.utils.pdf;

import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.entity.ContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.*;


/**
 * 根据PDF模板生成具体内容PDF
 */
public class PDFUtils {
    private static final Logger log = LoggerFactory.getLogger(PDFUtils.class);

    /**
     * @param fields
     * @param data
     * @throws IOException
     * @throws DocumentException
     */
    private static void fillData(AcroFields fields, Map<String, String> data) throws IOException, DocumentException {
        List<String> keys = new ArrayList<String>();
        Map<String, AcroFields.Item> formFields = fields.getFields();
        for (String key : data.keySet()) {
            if (formFields.containsKey(key)) {
                String value = data.get(key);
                // 为字段赋值,注意字段名称是区分大小写的
                fields.setField(key, value);
                keys.add(key);
            }
        }
        Iterator<String> itemsKey = formFields.keySet().iterator();
        while (itemsKey.hasNext()) {
            String itemKey = itemsKey.next();
            if (!keys.contains(itemKey)) {
                fields.setField(itemKey, " ");
            }
        }
    }

    /**
     * @param templatePdfPath 模板pdf路径
     * @param generatePdf    生成pdf路径
     * @param imagePath       图片路径
     * @param fitWidth        图片宽
     * @param fitHeight       图片高
     * @param data            数据
     */
    public MultipartFile getPDFMultipartFile(String templatePdfPath, String generatePdf,String imageFiledName, String imagePath,
                              Float fitWidth, Float fitHeight,Map<String, String> data) {
        ByteArrayOutputStream bos = null;
        InputStream inputStream = null ;
        MultipartFile file = null ;
        try {
            PdfReader reader = new PdfReader(templatePdfPath);
            // 将要生成的目标PDF文件名称
            bos = new ByteArrayOutputStream();
            // 使用中文字体
            PdfStamper ps = new PdfStamper(reader, bos);
            BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
            // 取出报表模板中的所有字段
            fontList.add(bf);
            AcroFields fields = ps.getAcroFields();
            fields.setSubstitutionFonts(fontList);
            //设置图片
            if (StringUtils.isNotBlank(imagePath)) {
                // 通过域名获取所在页和坐标,左下角为起点
                int pageno = fields.getFieldPositions(imageFiledName).get(0).page;
                Rectangle signrect = fields.getFieldPositions(imageFiledName).get(0).position;
                float x = signrect.getLeft();
                float y = signrect.getBottom();
                // 读图片
                Image image = Image.getInstance(imagePath);
                // 获取操作的页面
                PdfContentByte under = ps.getOverContent(pageno);
                // 这里控制图片的大小
                //image.scaleToFit(signrect.getWidth(), signrect.getHeight());
                image.scaleToFit(fitWidth, fitHeight);
                // 添加图片
                image.setAbsolutePosition(x, y);
                under.addImage(image);
                //移除图片的路径,要不然会把路径也设置上去
                data.remove(imageFiledName);
            }

            // 必须要调用这个,否则文档不会生成的  如果为false那么生成的PDF文件还能编辑,一定要设为true
            fillData(fields, data);
            ps.setFormFlattening(true);
            ps.close();

            byte[] testFile = bos.toByteArray();
            inputStream = new ByteArrayInputStream(testFile);
            try {
                file = new MockMultipartFile(generatePdf, generatePdf, ContentType.APPLICATION_OCTET_STREAM.toString(), inputStream);
            } catch (IOException e) {
                log.error(e.getMessage());
            }
        } catch (Exception e) {
            log.error(e.getMessage());
        } finally {
            if(inputStream != null ){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    log.error(e.getMessage());
                }
            }
        }
        return file;
    }
    /**
     * 生成到本地
     * @param templatePdfPath 模板pdf路径
     * @param generatePdfPath 生成pdf路径
     * @param data            数据
     */
    public String generatePDF(String templatePdfPath, String generatePdfPath, Map<String, String> data) {
        OutputStream fos = null;
        ByteArrayOutputStream bos = null;
        try {
            PdfReader reader = new PdfReader(templatePdfPath);
            // 将要生成的目标PDF文件名称
            bos = new ByteArrayOutputStream();
            // 使用中文字体
            PdfStamper ps = new PdfStamper(reader, bos);
            BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
            // 取出报表模板中的所有字段
            fontList.add(bf);
            AcroFields fields = ps.getAcroFields();
            fields.setSubstitutionFonts(fontList);
            // 必须要调用这个,否则文档不会生成的  如果为false那么生成的PDF文件还能编辑,一定要设为true
            fillData(fields, data);
            ps.setFormFlattening(true);
            ps.close();
            fos = new FileOutputStream(generatePdfPath);
            fos.write(bos.toByteArray());
            fos.flush();
            return generatePdfPath;
        } catch (Exception e) {
            log.error(e.getMessage());
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    log.error(e.getMessage());
                }
            }
        }
        return null;
    }

    /**
     * 获取生成文件的MultipartFile
     * @param templatePdfPath
     * @param generatePdf
     * @param data
     * @return
     */
    public MultipartFile getPDFMultipartFile(String templatePdfPath, String generatePdf, Map<String, String> data) {
        ByteArrayOutputStream bos = null;
        MultipartFile file = null ;
        InputStream inputStream = null ;
        try {
            PdfReader reader = new PdfReader(templatePdfPath);
            // 将要生成的目标PDF文件名称
            bos = new ByteArrayOutputStream();
            // 使用中文字体
            PdfStamper ps = new PdfStamper(reader, bos);
            String url = "/home/data/pdf_template/simfang.ttf";
            BaseFont bf = BaseFont.createFont(url, BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
            // 可能存在的问题:adober的版本不同造成中文不能显示,或者其他原因导致字体失效。该方法不是很稳妥
            // BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
            // 取出报表模板中的所有字段
            fontList.add(bf);
            AcroFields fields = ps.getAcroFields();
            fields.setSubstitutionFonts(fontList);
            // 必须要调用这个,否则文档不会生成的  如果为false那么生成的PDF文件还能编辑,一定要设为true
            fillData(fields, data);
            ps.setFormFlattening(true);
            ps.close();

            byte[] testFile = bos.toByteArray();
            inputStream = new ByteArrayInputStream(testFile);
            try {
                file = new MockMultipartFile(generatePdf, generatePdf, ContentType.APPLICATION_OCTET_STREAM.toString(), inputStream);
            } catch (IOException e) {
                log.error(e.getMessage());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(inputStream != null ){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return file;
    }
}

 

标签:段域,fields,bos,param,new,PDF,null,data,模板
From: https://www.cnblogs.com/LilLazy/p/17368734.html

相关文章

  • 「模板」前缀和
    阿巴阿巴阿巴输入n个数,给出m个询问,询问区间[x,y]的和。输入第一行为n和m,1<=n,m<=100000接下来一行为n个数,范围在0~100000之间接下来m行,每行两个数x,y,输出第x个数到第y个数之间所有数的和。保证x<=y输出m个数tips:1#include<bits/stdc++.h>2usingnamespacestd;3......
  • 扫描线【模板】
    扫描线用离散线段树实现时间复杂度\(O(n\logn)\)P5490【模板】扫描线题目描述代码#include<bits/stdc++.h>usingnamespacestd;#definemid(l+r)/2#definelsonl,mid,rt<<1#definersonmid,r,rt<<1|1#defineintlonglongconstintmaxn=2e5+10;intn,y[ma......
  • django模板语法
    django模板语法代码{%loadstatic%}<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title>{#<linkrel="stylesheet"href="/static/plugins/b......
  • python自动下载pdf文件—可分布下载=.= 一个demo
    代码如下:importioimportrequestsdefdownload_pdf(save_path,pdf_name,pdf_url):send_headers={"User-Agent":"Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/61.0.3163.100Safari/537.36&q......
  • 【模板】快读快写
    快读inlineintread(){ intx=0;boolf=1;chars=getchar(); while(s<'0'||s>'9'){if(s=='-')f=0;s=getchar();} while(s>='0'&&s<='9'){x=(x<<1)+(x<<3)+(s^48);s=getchar();} retur......
  • 可持久化字典树【模板】
    可持久化字典树P4735最大异或和#include<bits/stdc++.h>usingnamespacestd;constintmaxn=6e5+10;intn,m,sum[maxn],x,l,r,cnt=0;intch[maxn*25][2],ver[maxn*25],root[maxn];//ch表示字典树数组,ver表示每个接节点的版本(第几个字典树),root表示每个点所在的那个字典......
  • Django - json_script 模板语言,将queryset转换为前端json数据
     models.pyclassUser(models.Model):name=models.CharField(verbose_name="Name",max_length=64) serializer.pyclassUserSerializer(serializers.ModelSerializer):classMeta:model=Userfields=["name",......
  • Angular4_下拉框多选(支持响应式表单验证和模板驱动表单验证)
    支持Angular的响应式表单验证和模板驱动表单验证效果图:UsingwithTemplatedrivenFormsSkills*requiredAngularNameEmailAddress*requiredSubmitName [email protected]{"name":"","email&qu......
  • 【模板方法设计模式详解】C/Java/JS/Go/Python/TS不同语言实现
    简介模板方法模式(TemplateMethodPattern)也叫模板模式,是一种行为型模式。它定义了一个抽象公开类,包含基本的算法骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变算法的结构,只是重定义该算法的某些特定步骤。不同的子类以不同的方式实现这些抽象方法,从而对剩余的逻辑有......
  • python将pdf转为txt
    #encoding=utf8#-*-coding:utf-8-*-#pipinstallpypdf2-ihttps://pypi.tuna.tsinghua.edu.cn/simpleimportPyPDF2fromioimportStringIOcontent_all_list=[]#打开PDF文件并创建一个PyPDF2对象withopen('Scrum-Guide-Chinese-Simplified.pdf','r......