After using Adobe Acrobat DC to make a pdf template, use java to directly generate a pdf to a local specified path or export a pdf file

Reference article source:
springboot+itextpdf generates PDF files according to templates and downloads PDF files online
JAVA generates PDF files according to templates and exports them

Java splits a string into a string array according to a specified length

Thanks to the above bloggers for saving my life~~~

My system environment: win10, IDEA, jdk1.8

1. Download of Adobe Acrobat DC

Baidu link: Link: https://pan.baidu.com/s/1RSV8D6kXDbWeV2owgw2Zyg
Extraction code: f8p8
can be picked up by yourself.

2. Template preparation

1. Draw the template in word and save it as pdf

The pdf template I generated is shown in the image below.
pdf template

2. Open the software: Adobe Acrobat DC

The page is shown in the figure below, select [Tools] - [Prepare Form]
insert image description here
and put the above pdf file here
insert image description here
to enter the edit form page and edit the field (the field name must be consistent with the field name in the program). My edit is shown in the picture below.
insert image description here
Since in the [Remarks] field, we require underlined text, and the remark text may be a bit long, so I set it like this here, and my idea is as follows: 1. Set it in Adobe Acrobat
DC Created bz-line1, bz-line2, bz-line3 three text domains, and set their attributes respectively (just double-click the domain, text size, style, etc. can be set). As shown in the figure below:
insert image description here
2. In the program, read the data (string type), intercept the string according to the fixed length and put it into bz-line1, bz-line2, bz-line3 circularly. Later in the program I will show the stupid method I use. . . .

3. Actually. . If underlining is not required, you can directly check [Multiple Lines] in [Properties] to realize multi-text line breaks.
insert image description here
3. Save the edited template

Three, java implementation

1. Add Maven dependency

          <!-- PDF工具类 -->
		  <dependency>
		      <groupId>com.itextpdf</groupId>
		      <artifactId>itextpdf</artifactId>
		      <version>5.5.13</version>
		  </dependency>
		  <!-- PDF中文支持 -->
		  <dependency>
		      <groupId>com.itextpdf</groupId>
		      <artifactId>itext-asian</artifactId>
		      <version>5.2.0</version>
		  </dependency>

2. Directly generate pdf to the local specified path

(1), pdfUtils class

public class PdfUtils {
    
    

    private final static Logger log = LoggerFactory.getLogger(PdfUtils.class);

    // 利用模板生成pdf,这将直接保存到指定路径
    public static void pdfout(Map<String,Object> o,String templatePath,String newPDFPath) {
    
    

        PdfReader reader;
        FileOutputStream out=null;
        ByteArrayOutputStream bos=null;
        PdfStamper stamper;
        try {
    
    
        	//系统字体
            String prefixFont = "";
            String os = System.getProperties().getProperty("os.name");
            if (os.startsWith("win") || os.startsWith("Win")) {
    
    
                prefixFont = "C:\\Windows\\Fonts" + File.separator;
            } else {
    
    
                prefixFont = "/usr/share/fonts/chinese" + File.separator;
            }
            //必须加“,0”或“,1”,否则会报错:com.itextpdf.text.DocumentException: Font 'C:\Windows\Fonts\simsun.ttc' with 'Identity-H' is not recognized.
            BaseFont bf = BaseFont.createFont(prefixFont + "simsun.ttc,0" , BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

            out = new FileOutputStream(newPDFPath);// 输出流
            reader = new PdfReader(templatePath);// 读取pdf模板
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);
            AcroFields form = stamper.getAcroFields();
            //文字类的内容处理
            Map<String,String> datemap = (Map<String,String>)o.get("datemap");
            form.addSubstitutionFont(bf);
            for(String key : datemap.keySet()){
    
    
                //为了文字可以有下划线,并且换行,控制每行字数,当字数超过时,将剩余文字填充至下一备选域
                if ("hzbz".equals(key)){
    
    
                    String hzbz = datemap.get(key);
                    String[] hzbzArray = stringToStringArray(hzbz,24);

                    for(int i = 0; i < hzbzArray.length; i++){
    
    
                        String fkey = "hzbz-line" + (i+1);
                        form.setField(fkey,hzbzArray[i]);
                    }

                }else if("bz".equals(key)){
    
    

                    String bz = datemap.get(key);
                    String[] bzArray = stringToStringArray(bz,24);

                    for(int i = 0; i < bzArray.length; i++){
    
    
                        String fkey = "bz-line" + (i+1);
                        form.setField(fkey,bzArray[i]);
                    }

                }else{
    
    
                    String value = datemap.get(key);
                    form.setField(key,value);
                }

            }
            //图片类的内容处理
            Map<String, Image> imgmap = (Map<String,Image>)o.get("imgmap");
            for(String key : imgmap.keySet()) {
    
    
                Image value = imgmap.get(key);
                //String imgpath = value;
                Image image = value;
                int pageNo = form.getFieldPositions(key).get(0).page;
                Rectangle signRect = form.getFieldPositions(key).get(0).position;
                float x = signRect.getLeft();
                float y = signRect.getBottom();
                //根据路径读取图片
                //Image image = Image.getInstance(imgpath);
                //获取图片页面
                PdfContentByte under = stamper.getOverContent(pageNo);
                //图片大小自适应
                image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                //添加图片
                image.setAbsolutePosition(x, y);
                under.addImage(image);
            }
            stamper.setFormFlattening(true);// 如果为false,生成的PDF文件可以编辑,如果为true,生成的PDF文件不可以编辑
            stamper.close();
            Document doc = new Document(PageSize.A4, 50, 40, 40, 50);
            PdfCopy copy = new PdfCopy(doc, out);
            doc.open();

            //form.getTotalRevisions();
            int pages= stamper.getReader().getNumberOfPages();
            for(int i=1;i<=pages;i++){
    
    
                PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), i);
                copy.addPage(importPage);
            }
            doc.close();
        } catch (IOException e) {
    
    
            log.error("pdfout",e);
        } catch (DocumentException e) {
    
    
            log.error("pdfout",e);
        }finally {
    
    
            if(out!=null){
    
    
                try{
    
    
                    out.close();
                }catch(Exception e){
    
    

                }
            }
            if(bos!=null){
    
    
                try{
    
    
                    bos.close();
                }catch(Exception e){
    
    

                }

            }

        }
    }

    // 将字符串按照指定长度分割成字符串数组
    public static String[] stringToStringArray(String src, int length) {
    
    
        //检查参数是否合法
        if (null == src || src.equals("")) {
    
    
            return null;
        }

        if (length <= 0) {
    
    
            return null;
        }
        int n = (src.length() + length - 1) / length; //获取整个字符串可以被切割成字符子串的个数
        String[] split = new String[n];
        for (int i = 0; i < n; i++) {
    
    
            if (i < (n - 1)) {
    
    
                split[i] = src.substring(i * length, (i + 1) * length);
            } else {
    
    
                split[i] = src.substring(i * length);
            }
        }
        return split;
    }

    public static  byte[] inputstream2Bytes(InputStream inStream)  throws IOException{
    
    
        byte[] in_b = null;
        try{
    
    
            ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
            byte[] buff = new byte[100]; //buff用于存放循环读取的临时数据
            int rc = 0;
            while ((rc = inStream.read(buff, 0, 100)) > 0) {
    
    
                swapStream.write(buff, 0, rc);
            }
            in_b = swapStream.toByteArray(); //in_b为转换之后的结果

        }catch(Exception e){
    
    
            log.error("inputstream2Bytes",e);
        }finally {
    
    
            inStream.close();
        }
        return in_b;
    }

    /**
     * @Description: 文件转流
     */
    public static InputStream file2InputStream(File file)  throws IOException{
    
    
        return new FileInputStream(file);
    }

(2), controller layer

@Controller
@RequestMapping("/pdf")
public class PdfController {
    
    

    @PostMapping("/createPdf")
    @ResponseBody
    public DataObject CreatePdf() throws AppException {
    
    

        //1、调用数据库,获取数据
		//此处写读取数据的代码
		
        //2、将数据存为key-value
        //存文字信息
        Map<String,String> map = new HashMap();
        //存图像信息
        Map<String,Image> mapI = new HashMap();
        map.put("name","田XX");
        map.put("sex","女");
        map.put("grbh","123456789010");
        map.put("sfzh","000000000000000000");
        map.put("rylb","啊哦");
        map.put("time1","2021-9-27");
        map.put("ddyy1","啊哦");
        map.put("time2","");
        map.put("ddyy2","");
        map.put("hzbz","有的人一生默默无闻,有的人一生轰轰烈烈,甚至千古流芳,为什么会这样?因为默默无闻的人只是满足于现状,而不去想怎么轰轰烈烈过一生,不要求自己,去做");
        map.put("bz","有的人一生默默无闻,有的人一生轰轰烈烈,甚至千古流芳,为什么会这样?因为默默无闻的人只是满足于现状,而不去想怎么轰轰烈烈过一生,不要求自己,去做");
        try{
    
    
            //图片路径
            File pic_file = new File("F:\\1555074510295049.jpg");
            Image pic_image = Image.getInstance(inputstream2Bytes(file2InputStream(pic_file)));
            mapI.put("pic",pic_image);
        }catch(Exception e){
    
    
        }

        Map<String,Object> o=new HashMap();
        o.put("datemap",map);
        o.put("imgmap",mapI);

        // 模板路径
        String templatePath = "/META-INF/resources/static/template/template.pdf";
        // 生成的新文件路径
        String newPDFPath = "F:\\template_sc.pdf";
        pdfout(o,templatePath,newPDFPath);
        return DataObject.getInstance();
    }
}

(3) Front entrance

layui.sight.ajaxRequest({
    
    
     type : 'post',
     async : true,
     url : layui.sight.compileUrl('${rc.contextPath}/pdf/CreatePdf'),
     data : [],
     callback : function(data) {
    
    
         alert("成功!")
     },
     failedCallback : function(data) {
    
    }
});

3. Export PDF

(1) pdfUtils class

public class PdfUtils {
    
    

    private final static Logger log = LoggerFactory.getLogger(PdfUtils.class);

    /**
     * 利用模板生成pdf导出
     */
    public static void pdfExport(Map<String, Object> o, HttpServletResponse response) {
    
    

        // 模板路径
        String templatePath = "/META-INF/resources/static/template/template.pdf";

        File file = new File(templatePath);
        if (!file.exists()) {
    
    
            try {
    
    
                file.createNewFile();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
        PdfReader reader;
        ByteArrayOutputStream bos;
        PdfStamper stamper;
        OutputStream out = null;
        try {
    
    
            BaseFont bf = BaseFont.createFont("C:/Windows/Fonts/simfang.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            // 输出流
            response.setContentType("application/pdf");
            response.setHeader("Content-Disposition",
                    "attachment;fileName=" + URLEncoder.encode("template_scsc.pdf", "UTF-8"));
            out = new BufferedOutputStream(response.getOutputStream());
            // 读取pdf模板
            reader = new PdfReader(templatePath);
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);
            AcroFields form = stamper.getAcroFields();
            //文字类的内容处理
            Map<String,String> datemap = (Map<String,String>)o.get("datemap");
            form.addSubstitutionFont(bf);
            for(String key : datemap.keySet()){
    
    
                //为了文字可以有下划线,并且换行,控制每行字数,当字数超过时,将剩余文字填充至下一备选域
                if ("hzbz".equals(key)){
    
    
                    String hzbz = datemap.get(key);
                    String[] hzbzArray = stringToStringArray(hzbz,24);

                    for(int i = 0; i < hzbzArray.length; i++){
    
    
                        String fkey = "hzbz-line" + (i+1);
                        form.setField(fkey,hzbzArray[i]);
                    }

                }else if("bz".equals(key)){
    
    

                    String bz = datemap.get(key);
                    String[] bzArray = stringToStringArray(bz,24);

                    for(int i = 0; i < bzArray.length; i++){
    
    
                        String fkey = "bz-line" + (i+1);
                        form.setField(fkey,bzArray[i]);
                    }

                }else{
    
    
                    String value = datemap.get(key);
                    form.setField(key,value);
                }

            }
            //图片类的内容处理
            Map<String, Image> imgmap = (Map<String,Image>)o.get("imgmap");
            for(String key : imgmap.keySet()) {
    
    
                Image value = imgmap.get(key);
                //String imgpath = value;
                Image image = value;
                int pageNo = form.getFieldPositions(key).get(0).page;
                Rectangle signRect = form.getFieldPositions(key).get(0).position;
                float x = signRect.getLeft();
                float y = signRect.getBottom();
                //根据路径读取图片
                //Image image = Image.getInstance(imgpath);
                //获取图片页面
                PdfContentByte under = stamper.getOverContent(pageNo);
                //图片大小自适应
                image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                //添加图片
                image.setAbsolutePosition(x, y);
                under.addImage(image);
            }
            stamper.setFormFlattening(true);
            stamper.close();
            Document doc = new Document();
            PdfCopy copy = new PdfCopy(doc, out);
            doc.open();
            PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
            copy.addPage(importPage);
            doc.close();

        } catch (IOException | DocumentException e) {
    
    
            System.out.println(e);
        } finally {
    
    
            try {
    
    
                assert out != null;
                out.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
    }

    // 将字符串按照指定长度分割成字符串数组
    public static String[] stringToStringArray(String src, int length) {
    
    
        //检查参数是否合法
        if (null == src || src.equals("")) {
    
    
            return null;
        }

        if (length <= 0) {
    
    
            return null;
        }
        int n = (src.length() + length - 1) / length; //获取整个字符串可以被切割成字符子串的个数
        String[] split = new String[n];
        for (int i = 0; i < n; i++) {
    
    
            if (i < (n - 1)) {
    
    
                split[i] = src.substring(i * length, (i + 1) * length);
            } else {
    
    
                split[i] = src.substring(i * length);
            }
        }
        return split;
    }

    public static  byte[] inputstream2Bytes(InputStream inStream)  throws IOException{
    
    
        byte[] in_b = null;
        try{
    
    
            ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
            byte[] buff = new byte[100]; //buff用于存放循环读取的临时数据
            int rc = 0;
            while ((rc = inStream.read(buff, 0, 100)) > 0) {
    
    
                swapStream.write(buff, 0, rc);
            }
            in_b = swapStream.toByteArray(); //in_b为转换之后的结果

        }catch(Exception e){
    
    
            log.error("inputstream2Bytes",e);
        }finally {
    
    
            inStream.close();
        }
        return in_b;
    }

    /**
     * @Description: 文件转流
     */
    public static InputStream file2InputStream(File file)  throws IOException{
    
    
        return new FileInputStream(file);
    }

(2), controller layer

@Controller
@RequestMapping("/pdf")
public class PdfController {
    
    

    @RequestMapping("/exportPdf")
    public void exportPdf(HttpServletRequest request, HttpServletResponse response) throws AppException {
    
    
        
        //调用数据库,获取数据

        //将数据存为key-value
        //存文字信息
        Map<String,String> map = new HashMap();
        //存图像信息
        Map<String,Image> mapI = new HashMap();
        map.put("name","田XX");
        map.put("sex","女");
        map.put("grbh","12345678910");
        map.put("sfzh","00000000000000000");
        map.put("rylb","啊哦");
        map.put("time1","2021-9-27");
        map.put("ddyy1","啊哦");
        map.put("time2","");
        map.put("ddyy2","");
        map.put("hzbz","有的人一生默默无闻,有的人一生轰轰烈烈,甚至千古流芳,为什么会这样?因为默默无闻的人只是满足于现状,而不去想怎么轰轰烈烈过一生,不要求自己,去做");
        map.put("bz","有的人一生默默无闻,有的人一生轰轰烈烈,甚至千古流芳,为什么会这样?因为默默无闻的人只是满足于现状,而不去想怎么轰轰烈烈过一生,不要求自己,去做");
        try{
    
    
            //图片路径
            File pic_file = new File("F:\\1555074510295049.jpg");
            Image pic_image = Image.getInstance(inputstream2Bytes(file2InputStream(pic_file)));
            mapI.put("pic",pic_image);
        }catch(Exception e){
    
    
        }

        Map<String,Object> o=new HashMap();
        o.put("datemap",map);
        o.put("imgmap",mapI);

        pdfExport(o,response);
    }
}

(3) Front entrance

function down(){
    
    
    var url = layui.sight.compileUrl('${rc.contextPath}/pdf/exportPdf');
    window.open(encodeURI(url));
}

4. The final effect

insert image description here
The pictures are not well chosen. .

Five, there are problems

After the project is packaged, a null pointer error will be reported when the jar package is started. I forgot to copy the specific error description.

Solution:
Modify PdfUtils . After modification:

 /**
     * 利用模板生成pdf导出
     */
    public static void pdfExport(Map<String, Object> o, HttpServletResponse response) throws IOException {
    
    

        // 生成的新文件路径
        String filePath = "D:\\test.text";

        // 模板路径
        Resource resource = new ClassPathResource("/META-INF/resources/static/template/template.pdf");
        File inuModel = new File(filePath);
        FileUtils.copyInputStreamToFile(resource.getInputStream(), inuModel);


        PdfReader reader;
        ByteArrayOutputStream bos;
        PdfStamper stamper;
        OutputStream out = null;
        try {
    
    
            BaseFont bf = BaseFont.createFont("C:/Windows/Fonts/simfang.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            // 输出流
            response.setContentType("application/pdf");
            response.setHeader("Content-Disposition",
                    "attachment;fileName=" + URLEncoder.encode("template_scsc.pdf", "UTF-8"));
            out = new BufferedOutputStream(response.getOutputStream());
            // 读取pdf模板
            reader = new PdfReader(filePath);
            bos = new ByteArrayOutputStream();
            stamper = new PdfStamper(reader, bos);
            AcroFields form = stamper.getAcroFields();
            //文字类的内容处理
            Map<String,String> datemap = (Map<String,String>)o.get("datemap");
            form.addSubstitutionFont(bf);
            for(String key : datemap.keySet()){
    
    

                String value = datemap.get(key);
                form.setField(key,value);

            }
            //图片类的内容处理
            Map<String, Image> imgmap = (Map<String,Image>)o.get("imgmap");
            for(String key : imgmap.keySet()) {
    
    
                Image value = imgmap.get(key);
                //String imgpath = value;
                Image image = value;
                int pageNo = form.getFieldPositions(key).get(0).page;
                Rectangle signRect = form.getFieldPositions(key).get(0).position;
                float x = signRect.getLeft();
                float y = signRect.getBottom();
                //根据路径读取图片
                //Image image = Image.getInstance(imgpath);
                //获取图片页面
                PdfContentByte under = stamper.getOverContent(pageNo);
                //图片大小自适应
                image.scaleToFit(signRect.getWidth(), signRect.getHeight());
                //添加图片
                image.setAbsolutePosition(x, y);
                under.addImage(image);
            }
            stamper.setFormFlattening(true);
            stamper.close();
            Document doc = new Document();
            PdfCopy copy = new PdfCopy(doc, out);
            doc.open();
            PdfImportedPage importPage = copy.getImportedPage(new PdfReader(bos.toByteArray()), 1);
            copy.addPage(importPage);
            doc.close();

        } catch (IOException | DocumentException e) {
    
    
            System.out.println(e);
        } finally {
    
    
            try {
    
    
                assert out != null;
                out.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
    }

Guess you like

Origin blog.csdn.net/qq_42622871/article/details/121516207