我之所以发布这个问题,是因为许多开发人员或多或少地以不同的形式问同一个问题。我会自己回答这个问题(我是iText Group的创始人/首席技术官),这样它就可以成为“维基答案”如果堆栈溢出的“文档”特性仍然存在,那么这将是文档主题的一个很好的候选者。
我正在尝试将以下HTML文件转换为PDF:
<html>
<head>
<title>Colossal (movie)</title>
<style>
.poster { width: 120px;float: right; }
.director { font-style: italic; }
.description { font-family: serif; }
.imdb { font-size: 0.8em; }
a { color: red; }
</style>
</head>
<body>
<img src="img/colossal.jpg" class="poster" />
<h1>Colossal (2016)</h1>
<div class="director">Directed by Nacho Vigalondo</div>
<div class="description">Gloria is an out-of-work party girl
forced to leave her life in New York City, and move back home.
When reports surface that a giant creature is destroying Seoul,
she gradually comes to the realization that she is somehow connected
to this phenomenon.
</div>
<div class="imdb">Read more about this movie on
<a href="www.imdb.com/title/tt4680182">IMDB</a>
</div>
</body>
</html>
在浏览器中,这种超文本标记语言如下所示:
HTMLWorker根本不考虑CSS
当我使用HTMLWorker
时,我需要创建一个ImageProvider
,以避免一个错误通知我找不到图像。我还需要创建一个样式表
实例来更改一些样式:
public static class MyImageFactory implements ImageProvider {
public Image getImage(String src, Map<String, String> h,
ChainedProperties cprops, DocListener doc) {
try {
return Image.getInstance(
String.format("resources/html/img/%s",
src.substring(src.lastIndexOf("/") + 1)));
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
public static void main(String[] args) throws IOException, DocumentException {
Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream("results/htmlworker.pdf"));
document.open();
StyleSheet styles = new StyleSheet();
styles.loadStyle("imdb", "size", "-3");
HTMLWorker htmlWorker = new HTMLWorker(document, null, styles);
HashMap<String,Object> providers = new HashMap<String, Object>();
providers.put(HTMLWorker.IMG_PROVIDER, new MyImageFactory());
htmlWorker.setProviders(providers);
htmlWorker.parse(new FileReader("resources/html/sample.html"));
document.close();
}
结果如下:
出于某种原因,HTMLWorker
也会显示
当我看我的代码时,我发现我使用的很多对象和方法都被弃用了:
所以我决定升级到使用XML Worker。
使用XML Worker时找不到图像
我尝试了以下代码:
public static final String DEST = "results/xmlworker1.pdf";
public static final String HTML = "resources/html/sample.html";
public void createPdf(String file) throws IOException, DocumentException {
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
document.open();
XMLWorkerHelper.getInstance().parseXHtml(writer, document,
new FileInputStream(HTML));
document.close();
}
由此产生了以下PDF文件:
使用默认字体Helvetica而不是Times Roman;这是iText的典型情况(我应该在HTML中明确定义字体)。否则,CSS似乎受到尊重,但图像丢失,我没有收到错误消息。
使用
来解决这个问题。让我们看看这是否适用于XML Worker。HTMLWorker
,引发了一个异常,我可以通过引入一个ImageProvider
XML Worker并不支持所有CSS样式
我修改了我的代码如下:
public static final String DEST = "results/xmlworker2.pdf";
public static final String HTML = "resources/html/sample.html";
public static final String IMG_PATH = "resources/html/";
public void createPdf(String file) throws IOException, DocumentException {
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
document.open();
CSSResolver cssResolver =
XMLWorkerHelper.getInstance().getDefaultCssResolver(true);
HtmlPipelineContext htmlContext = new HtmlPipelineContext(null);
htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
htmlContext.setImageProvider(new AbstractImageProvider() {
public String getImageRootPath() {
return IMG_PATH;
}
});
PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);
XMLWorker worker = new XMLWorker(css, true);
XMLParser p = new XMLParser(worker);
p.parse(new FileInputStream(HTML));
document.close();
}
我的代码要长得多,但现在图像呈现:
图像比我使用HTMLWorker
渲染时大,这告诉我poster
类的CSS属性width
已被考虑,但float
属性被忽略。我该怎么解决这个问题?
所以问题归结为:我有一个特定的HTML文件,我试图转换成PDF。我已经做了很多工作,解决了一个又一个问题,但有一个具体的问题我无法解决:如何使iText尊重定义元素位置的CSS,例如float:right
?
当我的HTML包含表单元素时(例如
转换静态超文本标记语言页面,也可使用任何CSS样式:
HtmlConverter.convertToPdf(new File("./pdf-input.html"),new File("demo-html.pdf"));
对于spring Boot用户:使用SpringBoot和Thymeleaf转换动态HTML页面:
@RequestMapping(path = "/pdf")
public ResponseEntity<?> getPDF(HttpServletRequest request, HttpServletResponse response) throws IOException {
/* Do Business Logic*/
Order order = OrderHelper.getOrder();
/* Create HTML using Thymeleaf template Engine */
WebContext context = new WebContext(request, response, servletContext);
context.setVariable("orderEntry", order);
String orderHtml = templateEngine.process("order", context);
/* Setup Source and target I/O streams */
ByteArrayOutputStream target = new ByteArrayOutputStream();
ConverterProperties converterProperties = new ConverterProperties();
converterProperties.setBaseUri("http://localhost:8080");
/* Call convert method */
HtmlConverter.convertToPdf(orderHtml, target, converterProperties);
/* extract output as bytes */
byte[] bytes = target.toByteArray();
/* Send the response as downloadable PDF */
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=order.pdf")
.contentType(MediaType.APPLICATION_PDF)
.body(bytes);
}
使用iText 7和以下代码:
public void generatePDF(String htmlFile) {
try {
//HTML String
String htmlString = htmlFile;
//Setting destination
FileOutputStream fileOutputStream = new FileOutputStream(new File(dirPath + "/USER-16-PF-Report.pdf"));
PdfWriter pdfWriter = new PdfWriter(fileOutputStream);
ConverterProperties converterProperties = new ConverterProperties();
PdfDocument pdfDocument = new PdfDocument(pdfWriter);
//For setting the PAGE SIZE
pdfDocument.setDefaultPageSize(new PageSize(PageSize.A3));
Document document = HtmlConverter.convertToDocument(htmlFile, pdfDocument, converterProperties);
document.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
正如在超文本标记语言到PDF教程的介绍中所解释的,HTMLWorker
多年前就被弃用了。它不打算转换完整的超文本标记语言页面。它不知道超文本标记语言页面有一个
然后是XML工作者。XML Worker是用来解析XML的通用框架。作为概念证明,我们决定编写一些XHTML到PDF的功能,但我们不支持所有的HTML标记。例如:表单根本不受支持,而且很难支持用于定位内容的CSS。HTML格式的表单与PDF格式的表单非常不同。iText架构和HTML CSS架构之间也存在不匹配。渐渐地,我们扩展了XML Worker,主要是基于客户的请求,但XML Worker变成了一个有很多触角的怪物。
最终,我们决定从头开始重写iText,同时考虑到超文本标记语言CSS转换的要求。这导致了iText 7。在iText 7的基础上,我们创建了几个附加组件,在这个上下文中最重要的是pdfHTML。
使用最新版本的iText(iText 7.1.0 pdfHTML 2.0.0)将超文本标记语言从问题转换为PDF的代码简化为以下片段:
public static final String SRC = "src/main/resources/html/sample.html";
public static final String DEST = "target/results/sample.pdf";
public void createPdf(String src, String dest) throws IOException {
HtmlConverter.convertToPdf(new File(src), new File(dest));
}
结果如下:
正如你所看到的,这几乎是你所期望的结果。由于iText 7.1.0/PDFHTML2.0.0,默认字体为Times Roman。CSS受到尊重:图像现在漂浮在右侧。
当我建议升级到iText 7/pdfHTML 2时,开发人员通常会反对升级到更新的iText版本。请允许我回答我听到的前三个论点:
我需要使用免费的iText,而iText 7不是免费的/pdfHTML插件是封闭源代码的。
iText 7是使用AGPL发布的,就像iText 5和XML Worker一样。AGPL允许在开源项目中免费使用。如果您正在分发封闭源代码/专有产品(例如,您在SaaS环境中使用iText),则不能免费使用iText;在这种情况下,你必须购买商业许可证。iText 5已经是这样了;对于iText 7来说仍然如此。至于iText 5之前的版本:你根本不应该使用这些。关于pdfHTML:第一个版本实际上只作为封闭源代码软件提供。我们在iText Group内部进行了激烈的讨论:一方面,有些人希望避免公司大规模滥用资源,因为当这些开发人员告诉他们,开源与免费不一样时,他们不听开发人员的话。开发商告诉我们,他们的老板强迫他们做错事,他们无法说服老板购买商业许可证。另一方面,有人认为我们不应该因为开发人员的老板的错误行为而惩罚他们。最终,支持开源pdfHTML的人,即iText的开发者赢得了这场辩论。请证明他们没有错,并正确使用iText:如果您免费使用iText,请尊重AGPL;如果您在封闭源代码环境中使用iText,请确保您的老板购买了商业许可证。
我需要维护一个遗留系统,我必须使用旧的iText版本。
认真地维护还包括应用升级和迁移到正在使用的软件的新版本。如您所见,使用iText 7和pdfHTML时所需的代码非常简单,并且比以前所需的代码更不容易出错。迁移项目不应该花费太长时间。
我才刚刚开始,不知道iText 7;我是在完成我的项目后才发现的。
这就是为什么我要发布这个问题和答案。把你自己想象成一个极限程序员。扔掉你所有的代码,重新开始。你会注意到它没有你想象的那么多工作,你会睡得更好,因为你已经让你的项目经得起未来的考验,因为iText 5正在被淘汰。我们仍然为付费客户提供支持,但最终,我们将完全停止支持iText 5。
我将html表格从网页复制到excel,并尝试使用下面的代码,但没有结果。请就如何解决这个问题提出建议。我做了所有的实验,但没有得到正确的结果。
我正在尝试使用BeautifulSoup转换HTML文本块。以下是一个示例: 我试着做了这样的事情: ...但是这样我的span元素总是在新行上。这当然是一个简单的例子。有没有办法在超文本标记语言页面中获取文本,就像它在浏览器中呈现的方式一样(不需要css规则,只是div、spans、li等元素呈现的常规方式)在Python中?
旧标题:iTextSharp将HTML转换为PDF“文档没有页面” 我正在使用iTextSharp和xmlworker在ASP中将html从视图转换为PDF。净核心2.1 我尝试了网上找到的许多代码片段,但都生成了一个异常:“文档没有页面。” 以下是我目前的代码: 更新1 多亏了@Bruno Lowagie的建议,我升级到了iText7和pdfHTML,但我找不到太多关于它的教程。 我试过这个代码
我正在开发一个asp。net mvc项目,我正在使用一个html模板生成一个带有动态数据的发票文档,由于Handlebar,我填充了这些数据。生成的html通过使用iText 7转换为PDF,因为这是公司使用to所需的工具,但是我在将其转换为PDF时遇到了一个问题,因为html表显示数据,有时有足够的数据只适合一个页面,但在其他情况下,有许多行在分页符中相交,跨两个页面打印数据。每当数据不适合一页
对于上面的html内容,我如何使用Jsoup解析并获取文本 当我使用 我得到了这样的东西
我是新来的。我想解析html,但问题是我们必须在中指定的URL,我将在运行时从其他页面响应此URL。有没有办法将收到的网址传递到中?我读过这样的东西: 但是我不知道如何使用它。我很想知道是否有其他方法比jsoup更好。