itext7 html转pdf实现

原文:https://www.cnblogs.com/chengmuyu/p/9081770.html

公司最近做一个交易所项目,里面涉及一个需求就是将html模板,在填充数据后转换为pdf,这样防止数据更改,下面是具体实现

1 pom文件

按 Ctrl+C 复制代码

 

按 Ctrl+C 复制代码

2 html转pdf

复制代码

itext7进行html转换使用类:com.itextpdf.html2pdf.HtmlConverter
  它主要有三类操作:convertToPdf直接转换为pdf文件
           convertToDocument转为document文档,这样有利于进行pdf页面调整
           convertToElements拆解pdf标签
我这里因为html转换后会有多页,这里通过convertToDocument调整页面大小,在一页上显示所有内容;
同时我使用ByteArrayOutputStream类,这个的好处是不在本地生成文件,减少磁盘操作,但是这种方式也有人说效率不高,使用者可以斟酌后使用.
因为spring boot存在打包后resources目录文件获取不到的问题,所以我将pdf依赖的字体文件放到项目的根路径下(跟src目录同级).

复制代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

package com.ssth.exchanage.excenter.common.uitls;

 

import java.io.ByteArrayOutputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

 

import com.itextpdf.html2pdf.ConverterProperties;

import com.itextpdf.html2pdf.HtmlConverter;

import com.itextpdf.html2pdf.resolver.font.DefaultFontProvider;

import com.itextpdf.kernel.colors.Color;

import com.itextpdf.kernel.geom.PageSize;

import com.itextpdf.kernel.geom.Rectangle;

import com.itextpdf.kernel.pdf.PdfDocument;

import com.itextpdf.kernel.pdf.PdfPage;

import com.itextpdf.kernel.pdf.PdfWriter;

import com.itextpdf.kernel.pdf.canvas.PdfCanvas;

import com.itextpdf.kernel.pdf.canvas.draw.ILineDrawer;

import com.itextpdf.layout.Document;

import com.itextpdf.layout.element.LineSeparator;

 

public class PDFUtil {

    private static final String FONT = "./pdf/font/NotoSansCJKsc-Regular.otf";

 

    /**

     * @Description 将html转换为pdf文件

     * @param html html页面字符串

     * @return

     * @throws FileNotFoundException

     * @throws IOException

     */

    public ByteArrayOutputStream html2Pdf(String html) throws FileNotFoundException, IOException {

        ConverterProperties props = new ConverterProperties();

        DefaultFontProvider defaultFontProvider = new DefaultFontProvider(falsefalsefalse);

        defaultFontProvider.addFont(font);

        props.setFontProvider(defaultFontProvider);

        ByteArrayOutputStream bao = new ByteArrayOutputStream();

        PdfWriter writer = new PdfWriter(bao);

        PdfDocument pdf = new PdfDocument(writer);

        pdf.setDefaultPageSize(new PageSize(59514400));

        Document document = HtmlConverter.convertToDocument(html, pdf, props);

        EndPosition endPosition = new EndPosition();

        LineSeparator separator = new LineSeparator(endPosition);

        document.add(separator);

        document.getRenderer().close();

        PdfPage page = pdf.getPage(1);

        float y = endPosition.getY() - 36;

        page.setMediaBox(new Rectangle(0, y, 59514400 - y));

        document.close();

        return bao;

    }

 

    /**

     * 定义操作区域

     */

    class EndPosition implements ILineDrawer {

        // y坐标

        protected float y;

 

        /**

         * @Description: 获取y坐标

         * @return

         */

        public float getY() {

            return y;

        }

 

        /**

         * @Description: 操作画布特定区域

         * @param pdfCanvas:操作画布

         * @param rect:操作区域

         */

        @Override

        public void draw(PdfCanvas pdfCanvas, Rectangle rect) {

            this.y = rect.getY();

        }

 

        /**

         * @Description: 获取行颜色

         * @return

         */

        @Override

        public Color getColor() {

            return null;

        }

 

        /**

         * @Description: 获取行宽

         * @return

         */

        @Override

        public float getLineWidth() {

            return 0;

        }

 

        /**

         * @Description: 设置行颜色

         * @param color

         */

        @Override

        public void setColor(Color color) {

        }

 

        /**

         * @Description: 设置行宽

         * @param lineWidth:宽度

         */

        @Override

        public void setLineWidth(float lineWidth) {

        }

    }

}

3 流响应

核心是通过ByteArrayOutputStream.writeTo(HttpServletResponse.getOutputStream())方法

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

package com.huishi;

 

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.io.OutputStream;

import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Service;

import com.ssth.exchanage.excenter.common.exception.ResException;

import com.ssth.exchanage.excenter.common.uitls.DateUtil;

import com.ssth.exchanage.excenter.common.uitls.PDFUtil;

import com.ssth.exchanage.excenter.controller.response.RecordApplyParamRep;

import com.ssth.exchanage.excenter.service.ProductRecordService;

 

@Service

public class ProductRecordServiceImp implements ProductRecordService {

 

    /**

     * @Description 打印备案申请书

     * @param res http响应

     */

    @Override

    public void printRecord(HttpServletResponse res){

        try {

          String htmlStr = FileUtil.readFile(null);

          PDFUtil pdfUtil = new PDFUtil();

          ByteArrayOutputStream stream = pdfUtil.html2Pdf(htmlStr);

          res.setHeader("Expires""0");

          res.setHeader("Cache-Control""must-revalidate, post-check=0, pre-check=0");

              res.setHeader("Pragma""public");

          res.setContentType("application/pdf");

          OutputStream os = res.getOutputStream();

          stream.writeTo(os);

              os.flush();

              os.close();

        catch (IOException e) {

          log.error("printRecord {}",e.getMessage());

          throw new ResException("-1","服务内部错误,请稍后再试!");

        }

    }

}

备注:

itext7解决中文显示问题有两种解决方式:

1

2

3

4

1 引入对应的语言包,火狐浏览器预览生成的pdf可能存在部分中文乱码问题,同时因为加载了语言包,生成的pdf更大

使用NotoSansCJKsc-Regular.otf,同时在pom中引入com.itextpdf.font-asian包.

2 设置字体:通过默认字体生成,pdf文件和html大小几乎相同,不存在浏览器预览乱码问题

PdfFont font = PdfFontFactory.createFont("STSongStd-Light""UniGB-UCS2-H"false);

 

使用示例链接: https://github.com/liulei3/html2pdf 

参考文件:

html转pdf: https://developers.itextpdf.com/content/itext-7-examples/itext-7-converting-html-pdf

流响应:https://developers.itextpdf.com/content/best-itext-questions-stackoverview/general-questions-about-itext/itext7-how-can-i-serve-pdf-browser-without-storing-file-server-side

你可能感兴趣的:(JAVA,itext7)