我想使用iText将一系列html文件转换为PDF格式。
例如:如果有这些文件:
现在我要创建一个PDF文件,其中page1.html是第一页,page2.html是第二页,依此类推......
我知道如何将单个HTML文件转换为PDF,但我不知道如何将此操作产生的这些不同PDF合并为单个PDF。
答案 0 :(得分:7)
在开始之前:我不是C#开发人员,所以我不能在C#中给你一个例子。我编写的所有iText示例都是用Java编写的。幸运的是,iText和iTextSharp始终保持同步。在这个问题的上下文中,你可以放心,对iText起作用的任何东西都适用于iTextSharp,但是你必须做一些特定于C#的小改编。根据我从C#开发人员那里听到的,这通常不难实现。
关于答案:有两个答案,答案#2通常比答案#1更好,但是我给出了两个选项,因为可能存在特定情况,答案#1是更好。
测试数据:我创建了3个简单的HTML文件,每个文件都包含一些美国州的信息:
我们将使用XML Worker来解析这三个文件,因此我们需要一个PDF文件。
回答#1:请参阅ParseMultipleHtmlFiles1获取完整的代码示例,并multiple_html_pages1.pdf查看生成的PDF文件。
您说您已经成功将一个HTML文件转换为一个PDF文件。假设你是这样做的:
public byte[] parseHtml(String html) throws DocumentException, IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
// step 1
Document document = new Document();
// step 2
PdfWriter writer = PdfWriter.getInstance(document, baos);
// step 3
document.open();
// step 4
XMLWorkerHelper.getInstance().parseXHtml(writer, document,
new FileInputStream(html));
// step 5
document.close();
// return the bytes of the PDF
return baos.toByteArray();
}
这不是解析HTML文件的最有效方法(网站上还有其他示例),但这是最简单的方法。
如您所见,此方法将HTML解析为PDF文件,并以byte[]
的形式返回该PDF文件。由于我们要创建单个PDF,我们可以将此字节数组提供给PdfCopy
实例,以便我们可以连接多个文档。
假设我们有三个文件:
public static final String[] HTML = {
"resources/xml/page1.html",
"resources/xml/page2.html",
"resources/xml/page3.html"
};
我们可以遍历这三个文档,将它们逐个解析为byte[]
,使用PDF字节创建一个PdfReader
实例,然后使用PdfCopy
实例添加文档addDocument()
方法:
public void createPdf(String file) throws IOException, DocumentException {
Document document = new Document();
PdfCopy copy = new PdfCopy(document, new FileOutputStream(file));
document.open();
PdfReader reader;
for (String html : HTML) {
reader = new PdfReader(parseHtml(html));
copy.addDocument(reader);
reader.close();
}
document.close();
}
这解决了您的问题,但为什么我认为它不是最佳解决方案?
假设您需要使用需要嵌入的特殊字体。在这种情况下,每个单独的PDF文件都将包含该字体的子集。不同的文件需要不同的字体子集,而PdfCopy
(也不是PdfSmartCopy
)可以合并字体子集。这可能会导致臃肿的PDF文件中包含太多相同字体的字体子集。
我们如何解决这个问题?这是在答案#2中解释的。
回答#2:有关完整的代码示例,请参阅ParseMultipleHtmlFiles2;有关生成的PDF,请参阅multiple_html_pages2.pdf。您已经看到文件大小的差异:4.61 KB与5.05 KB(我们甚至没有引入嵌入字体)。
在这种情况下,我们不会像在答案#1的parseHtml()
方法中那样将HTML解析为PDF文件。相反,我们使用ElementList
方法将HTML解析为iText parseToElementList()
。此方法需要两个String
s。一个包含HTML代码,另一个包含CSS值。
我们使用实用程序方法将HTML文件读入String
。至于CSS值,我们可以将null
传递给parseToElementList()
,但在这种情况下,默认样式将被忽略。您会注意到,如果您未通过XML Worker附带的<h1>
,我们在HTML中引入的default.css
标记看起来会完全不同。
长话短说,这就是代码:
public void createPdf(String file) throws IOException, DocumentException {
Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream(file));
document.open();
String css = readCSS();
for (String htmlfile : HTML) {
String html = Utilities.readFileToString(htmlfile);
ElementList list = XMLWorkerHelper.parseToElementList(html, css);
for (Element e : list) {
document.add(e);
}
document.newPage();
}
document.close();
}
我们创建了一个Document
和一个PdfWriter
实例。我们将不同的HTML文件逐个解析为ElementList
,然后我们将所有元素添加到Document
。
如果您想要一个新页面,每次解析一个新的HTML文件时,我都会引入一个document.newPage()
。如果删除此行,则可以在一个页面上添加三个HTML页面(如果您选择回答#1,则不可能这样做。)