java html转pdf,itext7

2023-12-26 16:41:01

依赖

		<dependency>
			<groupId>com.itextpdf</groupId>
			<artifactId>html2pdf</artifactId>
			<version>3.0.2</version>
		</dependency>
		<dependency>
			<groupId>org.jsoup</groupId>
			<artifactId>jsoup</artifactId>
			<version>1.13.1</version>
		</dependency>
<!-- 解决中文乱码,但是有限 -->
		<dependency>
			<groupId>com.itextpdf</groupId>
			<artifactId>font-asian</artifactId>
			<version>7.1.13</version>
		</dependency>

处理


import cn.hutool.core.io.file.FileReader;
import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.html2pdf.attach.impl.OutlineHandler;
import com.itextpdf.io.font.otf.GlyphLine;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.WriterProperties;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.AreaBreak;
import com.itextpdf.layout.element.IBlockElement;
import com.itextpdf.layout.element.IElement;
import com.itextpdf.layout.font.FontProvider;
import com.itextpdf.layout.property.AreaBreakType;
import com.itextpdf.layout.property.Property;
import com.itextpdf.layout.splitting.DefaultSplitCharacters;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.ResourceUtils;

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

/**
 * 导出PDF工具类
 */
@Slf4j
public class PDFU {
	public static void main(String[] args) throws FileNotFoundException {
		File file = ResourceUtils.getFile("D:\\fornt_workspace\\new_file.html");
		String a = FileReader.create(file).readString();
		a = a.replace("field","a");
		a = a.replace("<div class=\"pagebreaker\"></div>","");
		createPDF(a);

	}
	/**
	 * 使用 iText 生成 PDF 文档
	 * @param htmlTmpStr   html 模板文件字符串
	 */
	public static ByteArrayOutputStream createPDF(String htmlTmpStr) {
		htmlTmpStr = htmlTmpStr.replace("field","a");
		htmlTmpStr = htmlTmpStr.replace("<div class=\"pagebreaker\"></div>","");
		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
		PdfWriter writer = new PdfWriter(outputStream, new WriterProperties().setFullCompressionMode(Boolean.TRUE));
		PdfDocument doc = new PdfDocument(writer);
		try {

			doc.setDefaultPageSize(PageSize.A4);
			FontProvider fontProvider = new FontProvider();
            // 如果需求小的话可以使用这个解决中文乱码
            // PdfFont pdfFont = PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H", false);
            // fontProvider.addFont(pdfFont.getFontProgram());

			// 设置中文字体文件的路径,可以在classpath目录下
			fontProvider.addDirectory("/usr/share/fonts/windows_fonts");
			fontProvider.addSystemFonts();
			ConverterProperties properties = new ConverterProperties();
			properties.setFontProvider(fontProvider);
			// PDF目录
			properties.setOutlineHandler(OutlineHandler.createStandardHandler());
			// 将html转为pdf代码块,按div生成页pdf
			Document document = new Document(doc);
            // 这个为了解决生成的pdf产生位移的问题
			document.setMargins(0,0,0,0);
			document.setProperty(Property.SPLIT_CHARACTERS, new DefaultSplitCharacters() {
				@Override
				public boolean isSplitCharacter(GlyphLine text, int glyphPos) {
					return true;//解决word-break: break-all;不兼容的问题,解决纯英文或数字不自动换行的问题
				}
			});
			document.setFontProvider(fontProvider);
			List<IElement> iElements = HtmlConverter.convertToElements(htmlTmpStr, properties);
			int size = iElements.size();
			for (int i = 0; i < size; i++) {
				IElement iElement = iElements.get(i);
				document.add((IBlockElement) iElement);
				if (!(i == size - 1)) { // 不是最后一页
					// 添加新的一页
					document.add(new AreaBreak(AreaBreakType.NEXT_PAGE));
				}
			}
			document.close();
//          测试生成文件使用
//			String  FileNamePath = "D:\\file\\ll.pdf";
//			FileOutputStream fis = new FileOutputStream(FileNamePath);
//			fis.write(outputStream.toByteArray());
//			result = outputStream.toByteArray();
		}catch (Throwable e){
			throw new RuntimeException("模板转换pdf失败,请重新填写或直接上传附件", e);
		}
		finally {
			try {
				doc.close();
				writer.close();
				outputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
				throw new RuntimeException("模板转换pdf失败,请重新填写或直接上传附件", e);
			}
		}
		return outputStream;
	}



	/**
	 * 根据文件相对路径返回一个 BufferedReader 流
	 *
	 * @param filePath
	 * @return
	 * @throws IOException
	 */
	public static BufferedReader returnReaderStream(String filePath) throws IOException {
		return new BufferedReader(new InputStreamReader(new ClassPathResource(filePath).getInputStream()));
	}

	/**
	 * 根据文件相对路径返回一个 BufferedReader 流
	 *
	 * @param filePath
	 * @return
	 * @throws IOException
	 */
	public static InputStream returnInputStream(String filePath) throws IOException {
		return new ClassPathResource(filePath).getInputStream();
	}

}

?解决在linxu上中文乱码

            // 如果需求小的话可以使用这个解决中文乱码
            // PdfFont pdfFont = PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H", false);
            // fontProvider.addFont(pdfFont.getFontProgram());

?font-asian 就是这个字体包,如果使用场景过多,可以把字体打进镜像


MAINTAINER xx@gmail.com

ENV TZ=Asia/Shanghai
ENV JAVA_OPTS="-Xms512m -Xmx1024m -Djava.security.egd=file:/dev/./urandom"

RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

RUN mkdir -p /usr/share/fonts/windows_fonts
COPY ./src/main/resources/fonts/* /usr/share/fonts/windows_fonts/

##安装字体
#RUN apt-get update && apt-get install -y fontconfig
#RUN fc-cache -f -v

# 安装字体
RUN yum install -y fontconfig

# 更新字体缓存
RUN fc-cache -f -v


#设置环境变量
ENV LANG=en_US.UTF-8 \
    LANGUAGE=en_US:en \
    LC_ALL=en_US.UTF-8

RUN mkdir -p /xx
WORKDIR /xx

EXPOSE 6666

ADD ./target/xx.jar ./
CMD java $JAVA_OPTS -jar xx.jar

需要把字体包放在resources/fonts下

加入字体文件,打包别忘了加上

在docker环境下,不知道为什么??fontProvider.addSystemFonts();? 获取系统字体是加载不到加入的字体文件的,但是查看系统字体是存在的,便使用
?? ??? ??? ?// 设置中文字体文件的路径
?? ??? ??? ?fontProvider.addDirectory("/usr/share/fonts/windows_fonts");
?? ??? ??? ?fontProvider.addSystemFonts();
直接制定了字体文件,以防万一又加了系统字体

catch (Throwable e){
			throw new RuntimeException("模板转换pdf失败,请重新填写或直接上传附件", e);
		}

?因为我这里是新增sql,但是回滚默认没有支持Throwable ,我就直接转换成了Exception,失败就不会新增sql了

?空白页,占位符显示问题

		a = a.replace("field","a");
		a = a.replace("<div class=\"pagebreaker\"></div>","");

?前端给的html中,<field>标签,itext7不识别,跟前端约定好了 ,直接替换,在<field>的样式的隐藏属性就生效了

<div class=\"pagebreaker\">每一页都会,都带着的话,每次生成会都带一个空白页

			String orginMd5 = SecureUtil.md5(htmlorg);
			String updateMd5 = SecureUtil.md5(htmlupdate);
			if(orginMd5.equals(updateMd5)){
				//如果一致,结束
				return ;
			}

?这里是 每次校验模板的html是否变化。。。👿

参考的原文章的大佬的文章?

iText7 HTML转PDF(页眉、页码、水印) + 浏览器在线预览_c# itext7 htmltopdf-CSDN博客

文章来源:https://blog.csdn.net/qq_37978148/article/details/135198926
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。