html转pdf(总结五种方法Java)

您所在的位置:网站首页 pdf转换为html html转pdf(总结五种方法Java)

html转pdf(总结五种方法Java)

2023-12-16 04:38| 来源: 网络整理| 查看: 265

来源:html转pdf(总结五种方法Java)_泰山码的博客-CSDN博客

html转pdf(总结五种方法Java)

Java 实现html转pdf,总结五种方法。推荐使用wkhtmltopdf,Itext

 

方法一:使用wkhtmltopdf

1、下载插件wkhtmltopdf https://wkhtmltopdf.org/downloads.html

2、本机测试 本目录下cmd进入 输入命令 wkhtmltopdf.exe ‪E:\学习文档\百度常用标签.html ‪E:\学习文档\百度常用标签.pdf

3、java代码实现 HtmlToPdf类

import java.io.File; public class HtmlToPdf { // wkhtmltopdf在系统中的路径 private static final String toPdfTool = "‪D:\\wkhtmltopdf\\bin\\wkhtmltopdf.exe"; /** * html转pdf * * @param srcPath html路径,可以是硬盘上的路径,也可以是网络路径 * @param destPath pdf保存路径 * @return 转换成功返回true */ public static boolean convert(String srcPath, String destPath,String toPdfTool){ File file = new File(destPath); File parent = file.getParentFile(); //如果pdf保存路径不存在,则创建路径 if(!parent.exists()){ parent.mkdirs(); } StringBuilder cmd = new StringBuilder(); cmd.append(toPdfTool); cmd.append(" "); cmd.append(" --header-line");//页眉下面的线 cmd.append(" --margin-top 3cm ");//设置页面上边距 (default 10mm) // cmd.append(" --header-html file:///"+WebUtil.getServletContext().getRealPath("")+FileUtil.convertSystemFilePath("\\style\\pdf\\head.html"));// (添加一个HTML页眉,后面是网址) cmd.append(" --header-spacing 5 ");// (设置页眉和内容的距离,默认0) //cmd.append(" --footer-center (设置在中心位置的页脚内容)");//设置在中心位置的页脚内容 //cmd.append(" --footer-html file:///"+WebUtil.getServletContext().getRealPath("")+FileUtil.convertSystemFilePath("\\style\\pdf\\foter.html"));// (添加一个HTML页脚,后面是网址) cmd.append(" --footer-line");//* 显示一条线在页脚内容上) cmd.append(" --footer-spacing 5 ");// (设置页脚和内容的距离) cmd.append(srcPath); cmd.append(" "); cmd.append(destPath); boolean result = true; try{ Process proc = Runtime.getRuntime().exec(cmd.toString()); HtmlToPdfInterceptor error = new HtmlToPdfInterceptor(proc.getErrorStream()); HtmlToPdfInterceptor output = new HtmlToPdfInterceptor(proc.getInputStream()); error.start(); output.start(); proc.waitFor(); }catch(Exception e){ result = false; e.printStackTrace(); } return result; } public static void main(String[] args) { String sourcePath = "https://blog.csdn.net/weixin_43981813/article/details/127895442?spm=1001.2014.3001.5502"; HtmlToPdf.convert(sourcePath, "D:\\testpdf.pdf",toPdfTool); System.out.println("0000"); } }

 HtmlToPdfInterceptor类

import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; public class HtmlToPdfInterceptor extends Thread { private InputStream is; public HtmlToPdfInterceptor(InputStream is){ this.is = is; } public void run(){ try{ InputStreamReader isr = new InputStreamReader(is, "utf-8"); BufferedReader br = new BufferedReader(isr); String line = null; while ((line = br.readLine()) != null) { System.out.println(line.toString()); //输出内容 } }catch (IOException e){ e.printStackTrace(); } } }

linux版本参考: https://blog.csdn.net/weixin_43981813/article/details/128257492

方法二:使用Itext

1、引入依赖

com.itextpdf html2pdf 3.0.2 com.itextpdf font-asian 7.1.13

2、解决水印和页码 只需实现实现com.itextpdf.kernel.events.IEventHandler接口即可

/** * 水印 */ public class WaterMarkEventHandler implements IEventHandler { /** * 水印内容 */ private String waterMarkContent; /** * 一页中有几列水印 */ private int waterMarkX; /** * 一页中每列有多少水印 */ private int waterMarkY; public WaterMarkEventHandler(String waterMarkContent) { this(waterMarkContent, 5, 5); } public WaterMarkEventHandler(String waterMarkContent, int waterMarkX, int waterMarkY) { this.waterMarkContent = waterMarkContent; this.waterMarkX = waterMarkX; this.waterMarkY = waterMarkY; } @Override public void handleEvent(Event event) { PdfDocumentEvent documentEvent = (PdfDocumentEvent) event; PdfDocument document = documentEvent.getDocument(); PdfPage page = documentEvent.getPage(); Rectangle pageSize = page.getPageSize(); PdfFont pdfFont = null; try { pdfFont = PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H", false); } catch (IOException e) { e.printStackTrace(); } PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), document); Paragraph waterMark = new Paragraph(waterMarkContent).setOpacity(0.5f); Canvas canvas = new Canvas(pdfCanvas, pageSize) .setFontColor(WebColors.getRGBColor("lightgray")) .setFontSize(16) .setFont(pdfFont); for (int i = 0; i < waterMarkX; i++) { for (int j = 0; j < waterMarkY; j++) { canvas.showTextAligned(waterMark, (150 + i * 300), (160 + j * 150), document.getNumberOfPages(), TextAlignment.CENTER, VerticalAlignment.BOTTOM, 120); } } canvas.close(); } } /** * 页码 */ public class PageEventHandler implements IEventHandler { @Override public void handleEvent(Event event) { PdfDocumentEvent documentEvent = (PdfDocumentEvent) event; PdfDocument document = documentEvent.getDocument(); PdfPage page = documentEvent.getPage(); Rectangle pageSize = page.getPageSize(); PdfFont pdfFont = null; try { pdfFont = PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H", false); } catch (IOException e) { e.printStackTrace(); } PdfCanvas pdfCanvas = new PdfCanvas(page.getLastContentStream(), page.getResources(), document); Canvas canvas = new Canvas(pdfCanvas, pageSize); float x = (pageSize.getLeft() + pageSize.getRight()) / 2; float y = pageSize.getBottom() + 15; Paragraph paragraph = new Paragraph("第" + document.getPageNumber(page) + "页/共" + document.getNumberOfPages() + "页") .setFontSize(10) .setFont(pdfFont); canvas.showTextAligned(paragraph, x, y, TextAlignment.CENTER); canvas.close(); } }

3、转换工具类

/** * Itext7转换工具类 */ @Slf4j public class HtmlToPdfUtils { /** * html转pdf * * @param inputStream 输入流 * @param waterMark 水印 * @param fontPath 字体路径,ttc后缀的字体需要添加,0 * @param outputStream 输出流 * @date : 2022/11/15 14:07 */ public static void convertToPdf(InputStream inputStream, String waterMark, String fontPath, OutputStream outputStream) throws IOException { PdfWriter pdfWriter = new PdfWriter(outputStream); PdfDocument pdfDocument = new PdfDocument(pdfWriter); //设置为A4大小 pdfDocument.setDefaultPageSize(PageSize.A4); //添加水印 pdfDocument.addEventHandler(PdfDocumentEvent.END_PAGE, new WaterMarkEventHandler(waterMark)); //添加中文字体支持 ConverterProperties properties = new ConverterProperties(); FontProvider fontProvider = new FontProvider(); // 设置字体 /*PdfFont sysFont = PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H", false); fontProvider.addFont(sysFont.getFontProgram(), "UniGB-UCS2-H");*/ //添加自定义字体,例如微软雅黑 if (StringUtils.isNotBlank(fontPath)) { PdfFont microsoft = PdfFontFactory.createFont(fontPath, PdfEncodings.IDENTITY_H, false); fontProvider.addFont(microsoft.getFontProgram(), PdfEncodings.IDENTITY_H); } properties.setFontProvider(fontProvider); // 读取Html文件流,查找出当中的;或出现类似的符号空格字符 inputStream = readInputStrem(inputStream); if (inputStream != null) { // 生成pdf文档 HtmlConverter.convertToPdf(inputStream, pdfDocument, properties); pdfWriter.close(); pdfDocument.close(); return; } else { log.error("转换失败!"); } } /** * 读取HTML 流文件,并查询当中的;或类似符号直接替换为空格 * * @param inputStream * @return */ private static InputStream readInputStrem(InputStream inputStream) { // 定义一些特殊字符的正则表达式 如: String regEx_special = "\\&[a-zA-Z]{1,10};"; try { //创建字节数组输出流,用来输出读取到的内容 ByteArrayOutputStream baos = new ByteArrayOutputStream(); //创建缓存大小 byte[] buffer = new byte[1024]; // 1KB //每次读取到内容的长度 int len = -1; //开始读取输入流中的内容 while ((len = inputStream.read(buffer)) != -1) { //当等于-1说明没有数据可以读取了 baos.write(buffer, 0, len); //把读取到的内容写到输出流中 } // 把字节数组转换为字符串 String content = baos.toString(); //关闭输入流和输出流 // inputStream.close(); baos.close(); // log.info("读取的内容:{}", content); // 判断HTML内容是否具有HTML的特殊字符标记 Pattern compile = Pattern.compile(regEx_special, Pattern.CASE_INSENSITIVE); Matcher matcher = compile.matcher(content); String replaceAll = matcher.replaceAll(""); // log.info("替换后的内容:{}", replaceAll); // 将字符串转化为输入流返回 InputStream stringStream = getStringStream(replaceAll); //返回结果 return stringStream; } catch (Exception e) { e.printStackTrace(); log.error("错误信息:{}", e.getMessage()); return null; } } /** * 将一个字符串转化为输入流 * @param sInputString 字符串 * @return */ public static InputStream getStringStream(String sInputString) { if (sInputString != null && !sInputString.trim().equals("")) { try { ByteArrayInputStream tInputStringStream = new ByteArrayInputStream(sInputString.getBytes()); return tInputStringStream; } catch (Exception e) { e.printStackTrace(); } } return null; } }

4、测试

@Slf4j public class Test { public static void main(String[] args) throws IOException { long startTime = System.currentTimeMillis(); // html文件所在相对路径 String htmlFile = "src/main/resources/html/index2.html"; // pdf文件存储相对路径 String pdfFile = "src/main/resources/x6.pdf"; // 自定义水印 String waterMarkText = ""; InputStream inputStream = new FileInputStream(htmlFile); OutputStream outputStream = new FileOutputStream(pdfFile); //微软雅黑在windows系统里的位置如下,linux系统直接拷贝该文件放在linux目录下即可 // String fontPath = "src/main/resources/font/STHeiti Light.ttc,0"; String fontPath = "src/main/resources/font/simsun.ttc,0"; HtmlToPdfUtils.convertToPdf(inputStream, waterMarkText, fontPath, outputStream); log.info("转换结束,耗时:{}ms",System.currentTimeMillis()-startTime); } }

5、注意事项

页面中不能出现html的特殊字符标记,如 等(代码中已经处理,所有都替换为空)可忽略页面中的图片路径,必须是在项目根路径后面的所有地址(相对路径)页面中的标签要符合规范,必须都具有结束标签等 方法三:使用Spire.Doc 将文档从一种格式转换为另一种格式是Spire.Doc的主要功能之一。这种转换只不过是加载和保存操作的组合。因此,使用Spire.DOC可以将文档从任何受支持的加载格式转换为任何受支持的保存格式。 spire.doc分为商业版和免费版,免费版只支持转换前3页,以免费版为例

1、增加一个maven仓库路径

com.e-iceblue http://repo.e-iceblue.cn/repository/maven-public/

依赖

e-iceblue spire.doc.free 3.9.0

2、转换工具类

/** * @Author:lzh * @Create:2022/11/19/18:04 * @Description:html转换pdf * @Version:1.0 */ public class Html3Pdf { public static void main(String[] args) throws IOException { } /** * 免费版,只支持前三页转换 * @param inputHtml HTML地址 * @param pdfName pdf保存地址 * @throws IOException */ public void spireDoc(String inputHtml,String pdfName) throws IOException { inputHtml = "src/main/resources/html/index2.html"; //新建Document对象 Document doc = new Document(); //添加section Section sec = doc.addSection(); // 将html转化为流字符串 String htmlText = readTextFromFile(inputHtml); //添加段落并写入HTML文本 sec.addParagraph().appendHTML(htmlText); pdfName = "src/main/resources/x4.pdf"; //将文档另存为PDF doc.saveToFile(pdfName, FileFormat.PDF); doc.dispose(); } /** * 将该路径的HTML页面转化为流字符串 * @param fileName 文件地址 * @return * @throws IOException */ public static String readTextFromFile(String fileName) throws IOException { StringBuffer sb = new StringBuffer(); BufferedReader br = new BufferedReader(new FileReader(fileName)); String content; while ((content = br.readLine()) != null) { sb.append(content); } return sb.toString(); } }

可参考:https://blog.csdn.net/csdnerM/article/details/120649237

方法四:使用Flying Sauser(技术老旧,对样式不支持)

Flying Sauser实现html2pdf,纠错能力差,支持中文、支持简单的页面和样式,开源 对html代码要求很严格。极易出现中文乱码问题

实现:

public class Html2Pdf { /** * HTML代码转PDF文档 * * @param content 待转换的HTML代码 * @param storagePath 保存为PDF文件的路径 */ public static void parsePdf(String content, String storagePath) { FileOutputStream os = null; try { File file = new File(storagePath); if(!file.exists()) { file.createNewFile(); } os = new FileOutputStream(file); ITextRenderer renderer = new ITextRenderer(); //解决中文支持问题 // ITextFontResolver resolver = renderer.getFontResolver(); // resolver.addFont("simhei.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); // resolver.addFont("simhei.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); renderer.setDocumentFromString(content); // 解决图片的相对路径问题,图片路径必须以file开头 // renderer.getSharedContext().setBaseURL("file:/"); renderer.layout(); renderer.createPDF(os); } catch (DocumentException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { if(null != os) { try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 对Html要求特别严格 * @param args * @throws IOException */ public static void main(String[] args) throws IOException { String htmlFilePath = ""; htmlFilePath = "F:/pdf/IText实现对PDF文档属性的基本设置 - 半亩池光 - 博客园.html"; StringBuilder content = new StringBuilder(); BufferedInputStream in; byte[] bys = new byte[1024]; int len; in = new BufferedInputStream(new FileInputStream(htmlFilePath)); while ((len = in.read(bys)) != -1) { content.append(new String(bys, 0, len)); } String html = closeHTML(content.toString()); html = html.replace(" "," "); parsePdf(html,"F:/pdf/wahaha.pdf"); } public static String closeHTML(String str){ List arrTags = new ArrayList(); arrTags.add("br"); arrTags.add("hr"); arrTags.add("link"); arrTags.add("meta"); arrTags.add("img"); arrTags.add("input"); for(int i=0;i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3