HTML To PDF JAVA Conversion (Without Losing Formatting)
In this tutorial, we will learn to convert Html files into pdf documents in our Java Applications. PDf format is a widely used document format when it comes to working with files. Java is a widely used language for developing enterprise-level applications. Therefore It is necessary for Java developers to learn how to generate HTML to pdf in java.
There are multiple use cases where we need to convert HTML into PDFs.
- Making Reports
- Converting Invoices into PDF
- Making a Pdf converter
- Creating Fillable PDF Forms
- Converting HTML files into PDF files . and many more.
We need a third-party HTML to pdf java library for generating pdf documents. There are multiple libraries but either they are paid, slow, or do not provide enough functionalities. We need an efficient library that is free for development, easy to use, and work with all application type which provides all necessary classes and functions to work with pdf files.
I will use the IronPDF library in this tutorial. This library is ideal as it prioritizes accuracy, ease of use, and speed. It is free for development, and work with all java application type and framework including spring boot application. It also works with Kotlin and Scala. So, if you are developing mobile, web, or desktop applications, It will work with all.
Let’s first have a look at the IronPDF Library before going any further.
IronPDF:
IronPdf is a library developed and maintained by Iron Software that helps Software Engineers to create, edit and extract PDF content in projects in Java.
IronPDF is supported by Java, Kotli, and Scala. It is developer-friendly and provides a variety of features in a single library.
The following are the features:
- Generating PDFs from HTML, URL, JavaScript, CSS, and many image formats
- Adding headers/footers, signatures, attachments, passwords, and security
- Performance optimization: Full Multithreading and Async support
- And many more! Visit their website to see all the code examples and a full list of their 50+ features*
This tutorial is designed in such a way that even a new programmer can easily understand and implement it. This tutorial assumed that you may have a basic understanding of Java.
Let’s create a project to convert HTML to pdf in java.
Create a New Project:
I am using IntelliJ IDE for java development. you can use any as per your preference.
So, the Step for creating a new project may differ from IDE to IDE.
Open, IntelliJ and Click on File> New > Project from Top Menu Bar. The following window will appear.
Name your Project, Select Location, Choose Language, JDK, and click on Create a Project.
New Project will be created.
Install IronPDF:
Now, we need to install the IronPDF java library to use in our project for converting HTML files into pdf documents.
Open Pom.XML file and add the following XML below the properties tag.
com.ironsoftware ironpdf 2022.11.0 org.slf4j slf4j-simple 2.0.3
Now, Open the Terminal and run the following command.
mvn install
This command will download and install the IronPDF.
Now, Open Main.Java file to actually write the code that will create pdf file from HTML Content.
Convert HTML to pdf document:
We first need to reference the IronPDF library to our Main.Java file. Write the following code snippet at the top of the file.
import com.ironsoftware.ironpdf.*;
Write the following code inside Main Function.
PdfDocument myPdf = PdfDocument.renderHtmlAsPdf("~Hello World~
Made with IronPDF!"); // Save the PdfDocument to a file try < myPdf.saveAs(Paths.get("html_saved.pdf")); >catch (IOException e)
renderHtmlAsPdf() function provided by PdfDocument class takes HTML string as an argument and convert HTML content to pdf file format.
saveAs() function will save the newly generated pdf file to the provided path in the argument.
Output:
Following is the output generated by the above code.
Convert URL to PDF document.
We can also generate pdf files from the web URL.
The following code demonstrates the example of generating the pdf document from the web URL.
PdfDocument myPdf = PdfDocument.renderUrlAsPdf ("https://en.wikipedia.org/wiki/PDF"); // Save the PdfDocument to a file try < myPdf.saveAs(Paths.get("html_saved.pdf")); >catch (IOException e)
renderUrlAsPdf() function provided by PdfDocument class takes the URL as an argument, and converges that URL into an HTML document.
Output:
Following is the output generated by the above-mentioned code, we can see that the pdf file generated by our code is 100% accurate.
Convert HTML file to PDF document:
The following code demonstrate the example of HTML file conversion into a pdf document. IronPDF really provides a very easy way to generate pdf from HTML files.
public static void main(String[] args) throws IOException < PdfDocument myPdf = PdfDocument.renderHtmlFileAsPdf("sample.html"); // Save the PdfDocument to a file try < myPdf.saveAs(Paths.get("html_saved.pdf")); >catch (IOException e) < throw new RuntimeException(e); >>
renderHtmlFileAsPdf() takes the path of the Html file as an argument, and converts the given file into a new pdf document.
Output:
Following is the output generated by the above code sample. Image and all styling including the font family generated in the pdf document is the exactly same as provided HTML file/web page.
Summary:
In this tutorial, we have learned a very easy way to convert HTML into a PDF document. We have demonstrated examples with code. We have converted HTML text to PDF, and we have also generated a PDF from an HTML File. Moreover, we have also learned to generate pdf files from URLs.
There are multiple useful and interesting features provided by IronPDF, but it is impossible to cover them all here. For more details, please click here.
I hope this article was understandable and easy to follow. For any queries, feel free to ask in the comment section.
Как web-страницу легко превратить в PDF?
Для меня было очень неожиданно то, что в хабе по Java практически нет информации по работе с PDF документами, поэтому я, из личного опыта, хочу на примере сервлета показать как легко можно любую web-страницу превратить в PDF документ.
Преамбула:
Напишем простой сервлет, который будет брать указанную нами web-страницу по HTTP протоколу и генерировать на её основе полноценный PDF документ.
Используемые библиотеки:
- Flying Saucer PDF — основная библиотека, которая поможет создать нам PDF документ из HTML/CSS
- iText — библиотека, которая включена в состав той, что описана выше, но я не мог не включить ее в список библиотек, т.к. именно на основе неё будет генерироваться PDF документ
- HTML Cleaner — библиотека, которая будет приводить наш HTML код в порядок
org.xhtmlrenderer flying-saucer-pdf 9.0.4 net.sourceforge.htmlcleaner htmlcleaner 2.6.1
Формирование страницы:
Одним из самый важных моментов является формирование страницы. Дело в том, что именно из самой страницы, посредством CSS, задаются параметры будущего PDF документа.
@font-face < font-family: "HabraFont"; src: url(http://localhost:8080/resources/fonts/tahoma.ttf); -fs-pdf-font-embed: embed; -fs-pdf-font-encoding: Identity-H; >@page < margin: 0px; padding: 0px; size: A4 portrait; >@media print < .new_page < page-break-after: always; >> body < background-image: url(http://localhost:8080/resources/images/background.png); >body * < padding: 0; margin: 0; >* < font-family: HabraFont; >#block < width: 90%; margin: auto; background-color: white; border: dashed #dbdbdb 1px; >#logo < margin-top: 5px; width: 100%; text-align: center; border-bottom: dashed #dbdbdb 1px; >#content Привет, хабр! Текущее время: <%=sdf.format(new Date())%>Новая страница!
Здесь хочу остановиться на нескольких моментах. Для начала самое важное: все пути должны быть абсолютными! Картинки, стили, адреса шрифтов и др., на всё должны быть прописаны абсолютные пути. А теперь пройдемся по CSS правилам (то, что начинается с символа @).
@ font-face — это правило, которое скажет нашему PDF генератору какой нужно взять шрифт, и откуда. Проблема в том, что библиотека, которая будет генерировать PDF документ не содержит шрифтов, включающих в себя кириллицу. Именно поэтому таким образом придется определять ВСЕ шрифты, которые используются в Вашей странице, пусть это будут даже стандартные шрифты: Arial, Verdana, Tahoma, и пр., в противном случае Вы рискуете не увидеть кириллицу в Вашем документе.
Обратите внимание на такие свойства как «-fs-pdf-font-embed: embed;» и «-fs-pdf-font-encoding: Identity-H;», эти свойства необходимы, их просто не забывайте добавлять.
@ page — это правило, которое задает отступы для PDF документа, ну и его размер. Здесь хотелось бы отметить, что если Вы укажите размер страницы A3 (а как показывает практика, это часто необходимо, т.к. страница не помещается в документ по ширине), то это не значит, что пользователю необходимо будет распечатывать документ (при желании) в формате A3, скорее просто весь контент будет пропорционально уменьшен/увеличен до желаемого (чаще A4). Т.е. относитесь к значению свойства size скептически, но знайте, что оно может сыграть для Вас ключевую роль.
@ media — правило, позволяющее создавать CSS классы для определенного типа устройств, в нашем случае это «print». Внутри этого правила мы создали класс, после которого наш генератор PDF документа создаст новую страницу.
Сервлет:
package ru.habrahabr.web_to_pdf.servlets; import org.htmlcleaner.CleanerProperties; import org.htmlcleaner.HtmlCleaner; import org.htmlcleaner.PrettyXmlSerializer; import org.htmlcleaner.TagNode; import org.xhtmlrenderer.pdf.ITextRenderer; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; /** * Date: 31.03.2014 * Time: 9:33 * * @author Ruslan Molchanov (ruslanys@gmail.com) */ public class PdfServlet extends HttpServlet < private static final String PAGE_TO_PARSE = "http://localhost:8080/page.jsp"; private static final String CHARSET = "UTF-8"; @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException < try < resp.setContentType("application/pdf"); byte[] pdfDoc = performPdfDocument(PAGE_TO_PARSE); resp.setContentLength(pdfDoc.length); resp.getOutputStream().write(pdfDoc); >catch (Exception ex) < resp.setContentType("text/html"); PrintWriter out = resp.getWriter(); out.write("Something wrong
"); ex.printStackTrace(out); ex.printStackTrace(); > > /** * Метод, подготавливащий PDF документ. * @param path путь до страницы * @return PDF документ * @throws Exception */ private byte[] performPdfDocument(String path) throws Exception < // Получаем HTML код страницы String html = getHtml(path); // Буффер, в котором будет лежать отформатированный HTML код ByteArrayOutputStream out = new ByteArrayOutputStream(); // Форматирование HTML кода /* эта процедура не обязательна, но я настоятельно рекомендую использовать этот блок */ HtmlCleaner cleaner = new HtmlCleaner(); CleanerProperties props = cleaner.getProperties(); props.setCharset(CHARSET); TagNode node = cleaner.clean(html); new PrettyXmlSerializer(props).writeToStream(node, out); // Создаем PDF из подготовленного HTML кода ITextRenderer renderer = new ITextRenderer(); renderer.setDocumentFromString(new String(out.toByteArray(), CHARSET)); renderer.layout(); /* заметьте, на этом этапе Вы можете записать PDF документ, скажем, в файл * но раз мы пишем сервлет, который будет возвращать PDF документ, * нам нужен массив байт, который мы отдадим пользователю */ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); renderer.createPDF(outputStream); // Завершаем работу renderer.finishPDF(); out.flush(); out.close(); byte[] result = outputStream.toByteArray(); outputStream.close(); return result; >private String getHtml(String path) throws IOException < URLConnection urlConnection = new URL(path).openConnection(); ((HttpURLConnection) urlConnection).setInstanceFollowRedirects(true); HttpURLConnection.setFollowRedirects(true); boolean redirect = false; // normally, 3xx is redirect int status = ((HttpURLConnection) urlConnection).getResponseCode(); if (HttpURLConnection.HTTP_OK != status && (HttpURLConnection.HTTP_MOVED_TEMP == status || HttpURLConnection.HTTP_MOVED_PERM == status || HttpURLConnection.HTTP_SEE_OTHER == status)) < redirect = true; >if (redirect) < // get redirect url from "location" header field String newUrl = urlConnection.getHeaderField("Location"); // open the new connnection again urlConnection = new URL(newUrl).openConnection(); >urlConnection.setConnectTimeout(30000); urlConnection.setReadTimeout(30000); BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), CHARSET)); StringBuilder sb = new StringBuilder(); String line; while (null != (line = in.readLine())) < sb.append(line).append("\n"); >return sb.toString().trim(); > @Override public String getServletInfo() < return "The servlet that generate and returns pdf file"; >>
Кстати, совсем не обязательно писать для этих целей сервлет, Вы можете перенести логику этого сервлета хоть в консольное приложение, которое будет сохранять PDF документы в файлы. Как Вы могли заметить, в сервлете не нужно ничего настраивать, менять, дополнять, и т.д. (ну за исключением пути до страницы и, возможно, кодировки), соответственно вся работа по подготовке PDF документа очень проста и происходит исключительно во вьюшке.
В конечном итоге у Вас должен получиться примерно такой PDF документ: github.com/ruslanys/example-web-to-pdf/blob/master/web-to-pdf-example.pdf
Я немного дополнил свой документ информацией (распарсил главную страницу Хабра) и у меня получился такой вот документ: github.com/ruslanys/sample-html-to-pdf/blob/master/web-to-pdf-habra.pdf
P.S. В принципе, на основе этого примера можно написать целый сервис, который будет по любому адресу страницы создавать PDF документ. Единственное, что будет необходимо сделать — это привести HTML код страницы в соответствие с нашими правилами, т.е. в первую очередь нужно будет переписать все относительные пути на абсолютные (благо это делается не сложно), и в соответствии с какой-то логикой задать размеры документа.