zoukankan      html  css  js  c++  java
  • itext7 html转pdf实现

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

    1 pom文件

         <dependency>
                <groupId>com.itextpdf</groupId>
                <artifactId>html2pdf</artifactId>
                <version>2.0.2</version>
            </dependency>
            <dependency>
                <groupId>com.itextpdf</groupId>
                <artifactId>font-asian</artifactId>
                <version>7.1.2</version>
            </dependency>             

    2 html转pdf

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

    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 引入对应的语言包,火狐浏览器预览生成的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

  • 相关阅读:
    Traits——信息输入界面
    Traits——安装/第一个界面
    opencv——如何安装opencv—python
    python——如何将列表中的元素全部取出来变成列表
    Pandas——循环路径下的文件将所有的txt文件进行合并
    股票交易
    良知?
    同源策略
    同步 异步 阻塞 非阻塞
    线程安全
  • 原文地址:https://www.cnblogs.com/chengmuyu/p/9081770.html
Copyright © 2011-2022 走看看