Skip to main content

PDF

Process custom PDF files.

Introduction​

Netuno generates PDF files with support for images, tables, fonts, and much more, through the PDF feature, which provides a low-code abstraction of iTextPDF for the various programming languages supported by Netuno.

The application that comes with Netuno called demo (demonstration application) contains many examples of possible code implementations in various languages, including the demonstration of PDF export through the export-pdf service located at:

  • netuno/apps/demo/server/services/samples/javascript/export-pdf.js

Initialization​

First, you need to create the object that will contain the context of the new document being created; by default, the page size is A4.

When creating the document, you define where it will be generated.

If nothing is defined, it will be generated in the service's data output, for example:

const pdfDocument = _pdf.newDocument()

To generate a PDF file inside the application's docs folder, you can do it like this:

const pdfDocument = _pdf.newDocument(_app.file("docs/file.pdf").output())

If you want to generate the document in a new file outside the application, for example:

const pdfDocument = _pdf.newDocument(_os.file("/tmp/file.pdf").output())

Or even in the application's storage:

const pdfDocument = _pdf.newDocument(_storage.filesystem("server", "file.pdf").output())

By default, the document is created with the A4 page format.

Page Format​

To customize the page format, simply specify it when creating the document.

Creates a new document for the service's data output with pages in letter format:

const pdfDocument = _pdf.newDocument(_pdf.pageSize("letter"))

Creates a new document for a file at the root of the application with B3 page format:

const pdfDocument = _pdf.newDocument(_app.file("file.pdf").output(), _pdf.pageSize("B3"))

Creates a new document in the application's storage with legal page format:

const pdfDocument = _pdf.newDocument(_storage.filesystem("server", "file.pdf").output(), _pdf.pageSize("legal"))

See the documentation about page size definitions.

PDF documents can be created with a custom page size definition; to do this, use pageSize by passing the page width and height values, for example:

_pdf.pageSize(50, 30)

HTTP Header​

To create a service in the REST API that returns a PDF file as data output, you need to add the HTTP protocol's Content-Type parameter to the header.

Example of how to set the content as PDF:

_header.contentType("pdf")

The pdf code is shorthand for:

_header.contentType("application/pdf")

Page Break​

To create a new page, areaBreak is used:

pdfDocument.add(
_pdf.areaBreak()
)

Paragraph​

Adds a new paragraph to the document:

pdfDocument.add(
_pdf.paragraph("My text here...")
.setFontSize(15)
)

To add a paragraph at a fixed position:

pdfDocument.add(
pdfDocument.add(
_pdf.paragraph("My fixed text...")
.setFixedPosition(100, 500, 200)
.setFontSize(15)
)
)

In the code above, in the setFixedPosition method, the first parameter is the X position (100), the second parameter is the Y position (500), and the third parameter is the width (200).

Attention: if Y is set to the value 0, it means it stays at the bottom of the page, so to move it up you need to increase the Y value; the higher the Y value, the closer to the top it will appear, but if it is too high beyond the page length, it will not be visible.

Documentation with all methods of the iText Paragraph object.

Font​

To define a native font, we can do it as follows:

const helvetica = _pdf.font("helvetica")
const helveticaBold = _pdf.font("helvetica-bold")
const helveticaBoldOblique = _pdf.font("helvetica-boldoblique")
const helveticaOblique = _pdf.font("helvetica-oblique")

To define a custom made font, we can use storage:

const viksiScript = _pdf.font(_storage.filesystem("server", "samples/export-pdf", "viksi-script.ttf"), true)

We can also use a file inside the application, as this example shows, where the font is inside the fonts folder at the root of the application:

const roboto = _pdf.font(_app.file("fonts/roboto.ttf"), true)

Or even use a file at any path on the system, so in this example the font is inside the fonts folder, which is inside the system's temporary files folder:

const roboto = _pdf.font(_os.file("/tmp/fonts/roboto.ttf"), true)

Documentation with all methods of the iText Font object.

To use the font in the texts, you must pass the font constant to the paragraph, like this:

pdfDocument.add(
_pdf.paragraph("Using the bold font.")
.setFont(helveticaBold)
.setFontSize(15)
)

Image​

Inserting images into a PDF document generated programmatically is done like this:

pdfDocument.add(
_pdf.image(_storage.filesystem("server", "samples/export-pdf", "logo.png"))
.scaleAbsolute(120, 36)
)

Note that the scaleAbsolute method is very useful for resizing and adjusting the image size.

Alternatively, we can use a file inside the application, as in this example:

const imageLogo = _pdf.image(_app.file("public/images/logo.png")

Or even use a file at any path on the system, as in this example:

const imageLogo = _pdf.image(_os.file("/tmp/images/pdf-logo.png")

To add an image at a fixed position:

pdfDocument.add(
imageLogo
.scaleAbsolute(120, 36)
.setFixedPosition(100, 500)
)

In the above, in the setFixedPosition method, the first parameter is the X position (100), and the second parameter is the Y position (500).

Attention: if Y is set to the value 0, it means it stays at the bottom of the page, so to move it up you need to increase the Y value; the higher the Y value, the closer to the top it will appear, but if it is too high beyond the page length, it will not be visible.

Documentation with all methods of the iText Image object.

Table​

It is possible to create tables, which allows presenting a data set in a more readable way.

The number of table columns is defined with the parameter: _pdf.table(numberColumns)

In the example below, numberColumns is the number 1, that is, one column.

Since we add two cells to the table, the second cell goes to the next row.

Note:

pdfDocument.add(
_pdf.table(1)
.addCell(
_pdf.cell()
.add(
_pdf.paragraph("Person")
.setFont(helvetica)
.setFontSize(10)
)
.setBorder(_pdf.border("solid", 2))
.setBackgroundColor(_pdf.colorRGB(1, 0, 0))
)
.addCell(
_pdf.cell()
.add(
_pdf.paragraph("Nicole")
.setFont(helvetica)
.setFontSize(10)
)
.setBackgroundColor(_pdf.colorGray(0.5))
)
)

The addCell method allows inserting the cell definitions with their respective content.

Documentation with all methods of the iText Cell object.

Closing and Saving the Document​

The document is only fully saved or generated when the close method is called, as follows:

pdfDocument.close()

Where the document is generated is defined at initialization, so it is when initializing the document that we define where the final document will be generated, whether in the service's data output (output) or in a file.

Editing a File​

It is possible to edit an existing PDF document, for example:

const pdfDocument = _pdf.openDocument(_app.file("file.pdf"))

The generated final document will be sent to the service's data output.

It is very useful for using a PDF as a base, as if it were a template.

Example of editing a document in the application's storage:

const pdfDocument = _pdf.openDocument(_storage.filesystem('server', 'file.pdf'))

Uses a document as a base but saves the changes to a new PDF file:

const pdfDocument = _pdf.openDocument(
_app.file("base-document.pdf"),
_app.file("final-document.pdf")
)

Example using a document in storage as a base but saving it to another one:

const pdfDocument = _pdf.openDocument(
_storage.filesystem("server", "base-contract.pdf"),
_storage.filesystem("server", "final-contract.pdf")
)

With the document loaded, we can add content, and when closing it with the close method at the end, the final document is then generated with the new content added programmatically.

Example of a service that uses an existing PDF as a template to generate a PDF file output with dynamically added content:

_header.contentType("pdf")

const pdfDocument = _pdf.openDocument(_app.file("template-1.pdf"))

pdfDocument.add(
_pdf.paragraph("My dynamic content.")
.setFixedPosition(37, 730, 100)
.setFontSize(15)
)

pdfDocument.close()

Reading a File​

To read a PDF document, extracting the text information.

We use the extract method, which gets all the PDF file data into a JSON object.

const pdfData = _pdf.extract(_app.file("file-1.pdf"))

_out.json(pdfData)

The returned JSON has the content key with all the text content of the PDF file, and has the metadata key with the various properties of the PDF file.

Here is an example of the JSON returned by extract:

{
"content": "All the text content of the PDF file goes here...",
"metadata":{
"Content-Type":"application/pdf",
"dc:format":"application/pdf; version=1.4",
"dc:title":"Linux 1",
"pdf:PDFVersion":"1.4",
"pdf:charsPerPage":"580",
"pdf:containsDamagedFont":"false",
"pdf:containsNonEmbeddedFont":"false",
"pdf:docinfo:producer":"Skia/PDF m125 Google Docs Renderer",
"pdf:docinfo:title":"File 1",
"pdf:encrypted":"false",
"xmpTPg:NPages":"3",
...
}
}

There are many other data items obtained in metadata but omitted in ... so the example does not become too long.

Converting​

It is possible to programmatically convert the PDF to text or even to HTML.

PDF to Text​

We can extract all the PDF file content as plain text using the method:

_pdf.toText(...)

Example of how to use it to read a file at the root of the application:

_out.print(_pdf.toText(_app.file("my-document.pdf")))

Or even using a file in the application's storage:

_out.print(_pdf.toText(_storage.filesystem("server", "my-document.pdf")))

PDF to HTML​

We can extract all the PDF file content as HTML using the method:

_pdf.toHTML(...)

Example of how to use it to read a file at the root of the application:

_out.print(_pdf.toHTML(_app.file("my-document.pdf")))

Or even using a file in the application's storage:

_out.print(_pdf.toHTML(_storage.filesystem("server", "my-document.pdf")))

HTML to PDF​

It is possible to generate PDF files from HTML code using the method:

_pdf.fromHTML(...)

Example of how to use it to generate a downloadable file in the service:

const icon = _app.file("public/images/icon.png");

const pdfFile = _pdf.fromHTML(`
<html>
<head>
<link href="https://fonts.googleapis.com/css2?family=Limelight&family=Roboto" rel="stylesheet">
<style>
* {
font-family: Roboto;
}
div.sidebar {
position: fixed;
top: 0;
bottom: 0;
left: 0;
width: 100px;
background: #1B5886;
}
div.sidebar > div {
position: absolute;
top: 350px;
transform: rotate(-90deg) translate(-50%, -34px);
font-family: Limelight;
font-size: 40px;
color: #89CFF1;
}
main {
padding-left: 150px;
}
h1 {
margin: 0 auto;
text-align: center;
font-family: Limelight;
color: #BA250E;
}
table {
margin: 0 auto;
border: 1px solid black;
border-spacing: 0;
border-collapse: collapse;
}
table > thead {
background: #40712A;
color: #fff;
}
table td, table th {
padding: 5px;
text-align: center;
}
table > tbody > tr:nth-child(even) {
background: #e1e1e1;
}
a {
font-family: Limelight;
font-size: 16px;
font-weight: bold;
text-decoration: none;
color: #1E5FB5;
}
</style>
</head>
<body>
<div class="sidebar">
<div>Demonstration</div>
</div>
<main>
<h1>PDF from HTML</h1>
<div style="text-align: center; margin: 30px 0;">
<img width="50" src="${icon.uri()}">
</div>
<p>
This is an example HTML for generating a PDF file.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam
tellus arcu, pharetra quis condimentum eget, dapibus convallis metus.
</p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Age</th>
</tr>
</thread>
<tbody>
<tr>
<td>Maria Luísa</td>
<td>23</td>
</tr>
<tr>
<td>José Matos</td>
<td>38</td>
</tr>
</tbody>
</table>
<hr style="margin-top: 50px; height: 1px; background: #50B6C6; border: none;"/>
<div>
<a href="https://netuno.org" target="_blank">Netuno.org</a>
</div>
</main>
</body>
</html>
`);

_header.contentTypePDF();
_out.copy(pdfFile.input());

Videos​

Below are some example videos on how to generate PDF files programmatically: