itext的pdf2html项目实践
itextadmin 发布于:2022-07-10 18:37:14
阅读:loading
本站功能在逐步实现后,开始完善站内的博客文章,在文章预览页增加了将当前文章下载为PDF文件(限制了用户必须登录)的功能实现,所以当对PDF的实现组件略有梳理后最终使用了PDF的itext中的html2pdf子项目,该项目可以将HTML转换为PDF,只需要导入依赖的maven坐标即可,无需依赖其它第三方服务插件等。
pdfHtml是itext7的附加组件,官网描述为pdfHtml,本人在本文中所声明的html2pdf想表达的是与pdfHtml是同一个意思,只是html2pdf更符合实际,将html代码转换为pdf文档,主要这个命名还是以官方在GitHub上提供的pdfHtml项目的示例源码定义的名称一致,参考项目示例源码地址为:https://github.com/itext/i7j-pdfhtml,导入IDEA后的工程名称为html2pdf。
在此前也将该项目下载下来后,逐个的运行了里面提供的部分Test案例,感觉还是很强大且值得实践的。关于HTML的代码片段主要关注的点有对于HTML标签的支持范围以及对于CSS样式和图片以及字体的支持,发现示例中对于常规的HTML标签均可支持,且对于外部的CSS文件以及<style>标签中的样式和标签内部的style属性定义的样式都可以支持。对于图片的支持也比较友好,主要是支持http在线图片和本地文件的图片以及base64文本的图片,对于字体库的支持也一样支持各种字体。
本次示例将不再过多的介绍官网提供的示例,也不再准备独立或纯净的测试项目实现,仅将文章内容的html导出为pdf文档下载功能实现的代码逻辑介绍即可,所以以近期编写的文章《使用JAXB解析XML文件》为例(可自行全站搜一搜找到该篇文章),该文章包含范的知识点细节有:
(1)字体支持中文,文字颜色为红色(由style定义);
(2)支持超链接,生成的PDF文档可以点击超链接打开浏览器访问对应的http地址,也同样支持http地址的附件下载;
(3)支持图片显示,html代码中的图片地址为http请求的路径,导出时会被存储为本地的图片不再依赖网络环境;
注:(1)原始的文章内容预览页面引入了有许多全局的CSS定义,如对于图片缩放至最大宽度100%的设置,导出时只是将富文本编辑器中的内容进行了读取,与文字预览时定义的样式并非完全相同,所以导出的图片并不会缩放至PDF文档的100%宽度大小,也未尝试若定了此处大小的css是否能够支持;(2)原始内容中包含了有源代码的代码块高亮插件,是JS的二次渲染,所以导出PDF时的代码块部分只是会显示原始的代码,并不会高亮;
原始文字导出后的PDF文件参考:使用JAXB解析XML文件.zip
参考代码给出的则比较简单,主要是itextpdf的maven坐标和功能中的导出下载逻辑,具体更多更细的代码转至本站开源的博客代码项目中查看。
<!-- itextpdf组件html转pdf -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>html2pdf</artifactId>
<version>4.0.1</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
package cn.chendd.blog.web.home.controller;
import ...;
/**
* 文章导出Controller
*
* @author chendd
* @date 2022/4/2 14:53
*/
@Api(value = "文章导出" , tags = "文章导出")
@ApiSort(60)
@Controller
@RequestMapping("/blog/export")
public class ArticleExportController extends BaseController {
@Resource
private ArticleExportService articleExportService;
@Value("${server.http-port}")
private Integer port;
/**
* 导出Pdf
*/
@GetMapping("/pdf/{id}")
@ApiOperation(value = "导出PDF" , notes = "导出文章内容数据")
@ApiOperationSupport(order = 10)
@ResponseBody
public void exportPdf(@ApiParam(name = "id" , value = "文章id") @PathVariable Long id) throws IOException {
ServletOutputStream outputStream = super.response.getOutputStream();
ArticleSingleContentResult article = this.articleExportService.getArticleContent(id);
try {
String articleContent = article.getEditorContent();
///处理html代码中路径不为http开头,使用html2pdf组件自带的根路径处理方式解决
/*{
String basePath = Http.getBaseHttpPath(request);
String filePrefix = "=\"/";
//1.处理相关地址中的图片地址,把/开头的地址增加项目访问前缀
articleContent = StringUtils.replace(articleContent , filePrefix , "=\"" + basePath + "/");
}*/
String fileName = DownloadNameUtil.browserDownloadName(article.getTitle() , request) + ".pdf";
String attachment = ContentDisposition.builder("attachment").filename(fileName).build().toString();
ConverterProperties converterProperties = new ConverterProperties();
converterProperties.setBaseUri(this.getBaseHttpPath(request));
converterProperties.setFontProvider(new DefaultFontProvider(true, true, true));
converterProperties.setCharset(StandardCharsets.UTF_8.name());
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader(HttpHeaders.CONTENT_DISPOSITION , attachment);
///注意:此处未生成落地本地磁盘文件,故无法拿到准确的下载文件地址,除非落地本地文件,再定时清理
///response.setHeader(HttpHeaders.CONTENT_LENGTH , String.valueOf(articleContent.getBytes().length));
HtmlConverter.convertToPdf(articleContent , outputStream , converterProperties);
} catch (Exception e) {
response.reset();
response.setContentType(MediaType.TEXT_HTML_VALUE);
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
throw e;
}
}
/**
* 获取http协议下的路径,也可以使用https协议的路径
* @param request request
* @return http路径
*/
private String getBaseHttpPath(HttpServletRequest request) {
StringBuilder basePathBuilder = new StringBuilder();
String portValue = "";
if(port != 80) {
portValue = ":" + port;
}
basePathBuilder.append("http://")
.append(request.getServerName()).append(portValue)
.append(request.getContextPath());
return basePathBuilder.toString();
}
}
itextpdf适用于小型企业、大型公司和ZF*机构,可以被视为首选的PDF技术,利用itextpdf提供的实现可以毫不费力的生成和操作PDF文档。itextpdf工具包提供了世界上文档最齐全、用途最广泛的PDF引擎之一(用Java和.NET编写),它不仅可以将PDF功能集成到您的工作流程中,还可以集成到您的应用程序、流程或产品中。本文主要是对itextpdf组件的html2pdf小小实践,更多还提供了pdfOCR、pdfOffice、pdf2Data等多个子项目,有机会再深入实践它们。早期的iText 5 Core已停止维护,不再开发,在新的项目中还是应与iText7的集成。
itext的官网地址为:https://itextpdf.com/,GitHub上的项目地址为:https://github.com/itext,以html2pdf为例,pdfHtml作为AGPL/商业软件获得双重许可,是免费/开源软件许可证,这并不意味着该软件是完全免费的!
点赞