Как разобрать несколько файлов HTML в один PDF?
Я хочу использовать iText для преобразования серии HTML-файлов в PDF.
Например: если есть эти файлы:
- page1.html
- page2.html
- page3.html
- ...
Теперь я хочу создать один PDF-файл, где page1.html - первая страница, page2.html - вторая страница и т. Д.
Я знаю, как преобразовать один файл HTML в PDF, но я не знаю, как объединить эти различные PDF-файлы, полученные в результате этой операции, в один PDF-файл.
1 ответ
Прежде чем мы начнем: я не разработчик C#, поэтому я не могу привести вам пример на C#. Все примеры iText, которые я пишу, написаны на Java. К счастью, iText и iTextSharp всегда синхронизированы. В контексте этого вопроса вы можете быть уверены, что все, что работает для iText, будет работать и для iTextSharp, но вам придется внести небольшие изменения, специфичные для C#. Из того, что я слышал от разработчиков на C#, этого обычно нетрудно достичь.
Что касается ответа: есть два ответа, и ответ № 2, как правило, лучше, чем ответ № 1, но я даю оба варианта, потому что могут быть конкретные случаи, когда ответ № 1 лучше.
Тестовые данные: я создал 3 простых HTML-файла, каждый из которых содержит некоторую информацию о штате в США:
- page1.html: Калифорния
- page2.html: Нью-Йорк
- page3.html: Массачусетс
Мы будем использовать XML Worker для анализа этих трех файлов, и в результате мы хотим получить один файл PDF.
Ответ № 1: см. ParseMultipleHtmlFiles1 для полного примера кода и множественный_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-файле и возвращает этот PDF-файл в виде byte[]
, Поскольку мы хотим создать один PDF, мы можем передать этот байтовый массив в PdfCopy
экземпляр, так что мы можем объединить несколько документов.
Предположим, что у нас есть три документа:
public static final String[] HTML = {
"resources/xml/page1.html",
"resources/xml/page2.html",
"resources/xml/page3.html"
};
Мы можем зациклить эти три документа, проанализировать их один за другим byte[]
, создать PdfReader
экземпляр с байтами PDF, и добавьте документ в 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 для полного примера кода и множественный_html_pages2.pdf для получающегося PDF. Вы уже видите разницу в размере файла: 4,61 КБ против 5,05 КБ (и мы даже не ввели встроенные шрифты).
В этом случае мы не анализируем HTML-файл PDF, как мы это делали в parseHtml()
Метод из ответа № 1. Вместо этого мы анализируем HTML в iText ElementList
с использованием parseToElementList()
метод. Этот метод требует двух String
s. Один содержит код HTML, другой содержит значения CSS.
Мы используем служебный метод для чтения файла HTML в String
, Что касается значения CSS, мы могли бы передать null
в parseToElementList()
, но в этом случае стили по умолчанию будут игнорироваться. Вы заметите, что <h1>
тег, который мы ввели в наш HTML, будет выглядеть совершенно иначе, если вы не передадите default.css
поставляется с XML Worker.
Короче говоря, это код:
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).