@DanielASathishKumar "Размер файла HTML составляет почти 1 ГБ". Надеюсь, вы ссылаетесь не только на HTML, но и на размер изображений и файлов, связанных с ним, и мне интересно, действительно ли вам нужны эти огромные файлы, встроенные в PDF. Возможно, вместо ссылки на корпоративный / публичный сервер?
у этот вопрос, потому что многие разработчики задают более или менее один и тот же вопрос в разных формах. Я сам отвечу на этот вопрос (я являюсь основателем / техническим директором 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>
В браузере этот HTML выглядит так:
Проблемы, с которыми я столкнулся:HTMLWorker вообще не учитывает CSS
Когда я использовалHTMLWorker
Мне нужно создатьImageProvider
чтобы избежать ошибки, которая сообщает мне, что изображение не может быть найдено. Мне также нужно создатьStyleSheet
Например, чтобы изменить некоторые стили:
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
также показывает содержание<title>
тег. Я не знаю, как этого избежать. CSS в заголовке не анализируется вообще, я должен определить все стили в моем коде, используяStyleSheet
объект.
Когда я смотрю на свой код, я вижу, что многие объекты и методы, которые я использую, устарели:
Поэтому я решил перейти на использование 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:
Вместо Times-Roman используется шрифт по умолчанию Helvetica; это типично для iText (я должен был явно определить шрифт в моем HTML). В противном случае, кажется, что CSS соблюдается, но изображение отсутствует, и я не получил сообщение об ошибке.
С участиемHTMLWorker
возникло исключение, и я смог решить проблему, введяImageProvider
, Давайте посмотрим, работает ли это для XML Worker.
Не все стили CSS поддерживаются в XML Worker
Я адаптировал свой код так:
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
который говорит мне, что атрибут CSSwidth
дляposter
класс учитывается, ноfloat
атрибут игнорируется. Как я могу это исправить?
Итак, вопрос сводится к следующему: у меня естьконкретный HTML-файл, который я пытаюсь преобразовать в PDF. Я проделал большую работу, решая одну проблему за другой, но есть однаконкретный проблема, которую я не могу решить: как заставить iText уважать CSS, который определяет положение элемента, напримерfloat: right
?
Когда мой HTML содержит элементы формы (такие как<input>
), эти элементы формы игнорируются.