Java integrates itextpdf to generate pdf by filling data in pdf template

Article directory

  • 1. Make a pdf template
    • 1.1, use excel to make a table
    • 1.2, convert to pdf
    • 1.3, set the form field
  • 2. Introducing POM dependencies
  • 3. Code implementation
    • 3.1. Tools
    • 3.2, entity object
    • 3.3、Controller

1. Make a pdf template

1.1, use excel to make a table

1.2, convert to pdf

I use the pdfelement official website address, which needs to be paid or cracked by myself, or other pdf editors can be used.

1.3, set form fields

2. Introduce POM dependencies

<!--pdf processing-->
 <dependency>
     <groupId>com.itextpdf</groupId>
     <artifactId>itextpdf</artifactId>
     <version>5.5.13</version>
 </dependency>
 <dependency>
     <groupId>com.itextpdf</groupId>
     <artifactId>itext-asian</artifactId>
     <version>5.2.0</version>
 </dependency>

3. Code implementation

Put the prepared pdf template into the project resources/pdf directory, as shown in the figure

3.1, Tools

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.util.ResourceUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * pdf related tools
 * Precautions:
 * 1. The time type needs to be converted into a string
 * 2. Only objects embedded in objects are supported, two-layer structure; objects embedded in objects and then objects embedded, the third layer of objects cannot be parsed, if this happens, it needs to be written recursively or parsed for the third time.
 *
 * @author zero
 */
@Slf4j
public class PdfUtil {<!-- -->

    private static boolean isPrimitiveOrWrapper(Class<?> clazz) {<!-- -->
        return clazz.isPrimitive() || clazz.getName().startsWith("java.lang");
    }

    private static Map<String, String> turnMap(Object object) {<!-- -->
        Map<String, Object> stringObjectMap = BeanUtil. beanToMap(object);
        Map<String, String> map = new HashMap<>(stringObjectMap. size() * 2);
        // Print out the attribute name and attribute value
        for (Map.Entry<String, Object> entry : stringObjectMap.entrySet()) {<!-- -->
            String key = entry. getKey();
            Object value = entry. getValue();
            if (ObjectUtil.isNotEmpty(value)) {<!-- -->
                //Basic type and package type
                if (isPrimitiveOrWrapper(value. getClass())) {<!-- -->
                    map.put(key, String.valueOf(value));
                } else {<!-- -->
                    // other types
                    if (value instanceof List) {<!-- -->
                        List<Object> list = (List) value;
                        for (int i = 0; i < list. size(); i ++ ) {<!-- -->
                            Object o = list. get(i);
                            Map<String, Object> stringObjectMap1 = BeanUtil. beanToMap(o);
                            for (Map.Entry<String, Object> entry1 : stringObjectMap1.entrySet()) {<!-- -->
                                String key1 = entry1. getKey();
                                Object value1 = entry1. getValue();
                                map.put(StrUtil.format("{}.{}{}", key, key1, i), String.valueOf(value1));
                            }
                        }
                    } else {<!-- -->
                        Map<String, Object> stringObjectMap1 = BeanUtil. beanToMap(value);
                        for (Map.Entry<String, Object> entry1 : stringObjectMap1.entrySet()) {<!-- -->
                            String key1 = entry1. getKey();
                            Object value1 = entry1. getValue();
                            map.put(StrUtil.format("{}.{}", key, key1), String.valueOf(value1));
                        }
                    }
                }
            }
        }
        return map;
    }

    public static void generatePdf(HttpServletRequest request,
                                   HttpServletResponse response,
                                   String templateName, Object object,
                                   boolean download) {<!-- -->
        try (OutputStream responseOutputStream = response. getOutputStream();
             ByteArrayOutputStream fileOut = new ByteArrayOutputStream()) {<!-- -->
             //The position of the template in the project
            Resource resource = new PathMatchingResourcePatternResolver()
                    .getResource(ResourceUtils.CLASSPATH_URL_PREFIX + "pdf/" + templateName);
            PdfReader reader = new PdfReader(resource. getInputStream());
            PdfStamper ps = new PdfStamper(reader, fileOut);
// BaseFont bf = BaseFont.createFont("STSong-Light","UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA_BOLD, BaseFont.WINANSI, BaseFont.EMBEDDED);
            ArrayList<BaseFont> fontList = new ArrayList<>();
            fontList. add(bf);
            //Retrieve all fields in the report template
            AcroFields fields = ps. getAcroFields();
            fields.setSubstitutionFonts(fontList);
            PdfUtil. fillData(fields, PdfUtil. turnMap(object));
            //This must be called, otherwise the document will not be generated If it is false, the generated PDF file can still be edited, it must be set to true
            ps.setFormFlattening(true);
            ps. close();
            if (download) {<!-- -->
                writerFile(request, response, templateName, false);
            }
            fileOut.writeTo(responseOutputStream);
        } catch (Exception e) {<!-- -->
            log.error("pdf generated exception:", e);
            throw new RuntimeException("The operation is abnormal, please contact the administrator!");
        }
    }

    /**
     * Data input
     *
     * @param fields
     * @param data
     * @throws IOException
     * @throws DocumentException
     */
    private static void fillData(AcroFields fields, Map<String, String> data) throws IOException, DocumentException {<!-- -->
        Map<String, AcroFields.Item> formFields = fields.getFields();
        for (String key : data.keySet()) {<!-- -->
            if (formFields. containsKey(key)) {<!-- -->
                String value = data. get(key);
                // Assign values to fields, note that field names are case-sensitive
                fields.setField(key, value);
            }
        }
    }

    /**
     * write out the file
     *
     * @param request
     * @param response
     * @param fileName
     * @param deleteOnExit Whether to delete local files
     */
    private static void writerFile(HttpServletRequest request,
                                   HttpServletResponse response,
                                   String fileName,
                                   boolean deleteOnExit) throws IOException {<!-- -->
        File file = new File("/" + fileName);
        file. createNewFile();
        response.setCharacterEncoding(request.getCharacterEncoding());
        response.setContentType("application/pdf");
        try (FileInputStream fis = new FileInputStream(file);) {<!-- -->
            //This is mainly to prevent the downloaded PDF file name from being garbled
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(file.getName(), "UTF-8"));
            IOUtils.copy(fis, response.getOutputStream());
            response.flushBuffer();

            if (deleteOnExit) {<!-- -->
                file.deleteOnExit();
            }
        } catch (Exception e) {<!-- -->
            log.error("pdf generated exception 1:", e);
            throw new RuntimeException("Operation exception 1, please contact the administrator!");
        }
    }
}

3.2, entity object

import lombok.Data;

import java.util.List;

/**
 * @author zero
 */
@Data
public class TestDto {<!-- -->
    private String name;
    private String birthday;
    private Other other;
    private List<Other> otherList;

    @Data
    public static class Other {<!-- -->
        private String career;
        private String company;
    }

}

3.3, Controller

import com.ymf.base.utils.PdfUtil;
import com.ymf.server.visitor.domain.dto.TestDto;
import io.swagger.annotations.Api;
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.util.ArrayList;
import java.util.List;

/**
 * Test control layer
 *
 * @author zero
 */
@RestController
@RequestMapping("test")
@Api(tags = "Test")
public class TestController {<!-- -->

    @GetMapping("/pdf")
    public void pdf(HttpServletRequest request, HttpServletResponse response) {<!-- -->
        TestDto testDto = new TestDto();
        testDto.setName("Zhang San");
        testDto.setBirthday("2020-12-12");
        TestDto.Other other = new TestDto.Other();
        other.setCareer("Career");
        other.setCompany("Byte does not jump");
        testDto.setOther(other);
        List<TestDto. Other> list = new ArrayList<>();
        for (int i = 0; i <= 2; i ++ ) {<!-- -->
            TestDto.Other other1 = new TestDto.Other();
            other1.setCareer("Career" + i);
            other1.setCompany("Byte does not jump" + i);
            list. add(other1);
        }
        testDto.setOtherList(list);
        PdfUtil.generatePdf(request, response, "test.pdf", testDto, false);
    }

Browser access ip:port/test/pdf, where ip is your ip address, port is your port, and the access results are as follows: