A Swift library that interacts with Gotenberg's different modules to convert a variety of document formats to PDF files.
To incorporate gotenberg-kit
into your project, follow the snippets below for SPM dependencies.
.package(url: "https://github.com/thoven87/gotenberg-kit.git", from: "0.1.0")
.target(name: "MyApp", dependencies: [.product(name: "GotenbergKit", package: "gotenberg-kit")]),
Before attempting to use GotenbergKit
, be sure you install Docker if you have not already done so.
Once the docker Daemon is up and running, you can start a default Docker container of Gotenberg as follows:
docker run --rm -p 7100:7100 gotenberg/gotenberg:8 gotenberg --api-port=7100
Create an instance of Gotenberg
class and pass your Gotenberg
endpoint
url as a constructor parameter.
let client = GotenbergClient(
baseURL: URL(string: ProcessInfo.processInfo.environment["GOTENBERG_URL"] ?? "http://localhost:7100")!
)
Gotenberg introduces basic authentication support starting from version 8.4.0. Suppose you are running a Docker container using the command below:
docker run --rm -p 3000:3000 \
-e GOTENBERG_API_BASIC_AUTH_USERNAME=gotenberg \
-e GOTENBERG_API_BASIC_AUTH_PASSWORD=password \
gotenberg/gotenberg:8 gotenberg --api-enable-basic-auth
To integrate this setup with Chromiumly, you need to update your client instance as outlined below:
let client = GotenbergClient(
baseURL: URL(
string: ProcessInfo.processInfo.environment["GOTENBERG_URL"] ?? "http://localhost:7100"
)!,
username: "gotenberg",
password: "password"
)
To implement advanced authentication or add custom HTTP headers to your requests, you can use the customHttpHeaders
option during initialization or for every function call. This allows you to pass additional headers, such as authentication tokens or custom metadata, with each API call.
For example, you can include a Bearer token for authentication along with a custom header as follows:
let client = GotenbergClient(
baseURL: URL(
string: ProcessInfo.processInfo.environment["GOTENBERG_URL"] ?? "http://localhost:7100"
)!
)
let token = try await generateToken()
let response = try await client.convert(
url: URL(string: "https://swift.org")!,
clientHTTPHeaders: [
"Authorization": "Bearer \(token)",
"X-Custom-Header": "value",
]
)
GotenbergKit exposes different funcs that serve as wrappers to Gotenberg's routes
GotenbergKit
client comes with a convert
function that call one of Chromium's routes to convert html
, markdown
files, or a url
to a GotenbergResponse
which holds the content of the converted PDF file.
convert
expects two parameters; the first parameter represents what will be converted (i.e. url
, html
, or markdown
files), and the second one is a ChromiumOptions
parameter.
let response = try await client.convertUrl("https://gotenberg.dev/")
let response = try await client.capture(url: URL(string: "https://gotenberg.dev/")!)
The only requirement is that one of the files name should be index.html
.
let index = try Data(contentsOf: URL(string:"path/to/index.html"))
let header = try Data(contentsOf: URL(string:"path/to/header.html"))
let response = try await client.convertHtml(
documents: [
"index.html": index,
"header.html": header
]
)
let response = try await client.capture(
htmlString: "<html>CONTENT</html>"
)
This route accepts an index.html
file plus a markdown file.
let html = """
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My PDF</title>
</head>
<body>
{{ toHTML "file.md" }}
</body>
"""
let response = try await client.convertMarkdown(
files: [
"index.html": html.data(using: .utf8)!,
"file.md": "Markdown Content".data(using: .utf8)!
]
)
let response = try await client.capture(
html: html.data(using: .utf8)!,
markdown: "Markdown Content".data(using: .utf8)!
)
Each convert()
method takes an optional properties
parameter of the following type which dictates how the PDF generated
file will look like.
ChromiumOptions
In addition to the ChromiumOptions
customization options, the convert()
method also accepts a set of parameters to further enhance the versatility of the conversion process.
Similarly, the capture()
function takes an optional properties
parameter of the specified type, influencing the appearance of the captured screenshot file.
ScreenshotOptions
The LibreOffice
utility comes with a function called convertWithLibreOffice
. This function interacts with LibreOffice route to convert different documents to PDF files. You can find the file extensions
accepted here.
let response = try await client.convertWithLibreOffice(
urls: [
.init(url: "https://someurl.com/myfile.csv"),
.init(url: "https://someurl.com/myfile.odt"),
.init(url: "https://someurl.com/myfile.doc"),
.init(url: "https://someurl.com/myfile.pdf")
],
)
Similarly to Chromium's route convert
function, this function takes the following optional parameters :
LibreOfficeConversionOptions
Note: not setting merge to true will return a zip file containing all PDF files
The PDFEngines
funcs interacts with Gotenberg's PDF Engines routes to manipulate PDF files.
This function interacts with PDF Engines convertion route to transform PDF files into the requested PDF/A format and/or PDF/UA.
let response = try await client.convertWithPDFEngines(
documents: [
"file_1.pdf": Data,
"file_2.pdf": Data
],
options: PDFEngineOptions(
pdfua: true,
format: .A1B
)
)
let response = try await client.convertWithPDFEngines(
urls: [
.init(url: "https://someurl.com/myfile.pdf")
],
options: PDFEngineOptions(
pdfua: true,
format: .A1B
)
)
These functions interact with PDF Engines merge route which gathers different engines that can manipulate and merge PDF files such as: PDFtk, PDFcpu, QPDF, and UNO.
let response = try await client.mergeWithPDFEngines(
documents: [
"file_1.pdf": Data,
"file_2.pdf": Data
],
options: PDFEngineOptions(
pdfua: true,
format: .A1B
)
)
let response = try await client.mergeWithPDFEngines(
urls: [
.init(url: "https://someurl.com/myfile.pdf")
],
options: PDFEngineOptions(
pdfua: true,
format: .A1B
)
)
This function reads metadata from the provided PDF files.
let response = try await client.readPDFMetadata(
urls: [
.init(url: "https://someurl.com/myfile.pdf")
],
)
let response = try await client.readPDFMetadata(
documents: [
"file_1.pdf": Data,
"file_2.pdf": Data
]
)
This function writes metadata to the provided PDF files.
let response = try await client.writePDFMetadata(
urls: [
.init(url: "https://someurl.com/myfile.pdf")
],
metadata: [
"Author": "Stevenson Michel",
"Title": "GotenbergKit"
"Keywords": ["pdf"', "gotenberg", "swift"]
]
)
Referr to ExifTool for a comprehensive list of accessible metadata options.
Each Chromium and LibreOffice route has a split
parameter that allows splitting a PDF file into multiple files. The split
parameter is an object with the following properties:
mode
: the mode of the split. It can bepages
orintervals
.span
: the span of the split. It is a string that represents the range of pages to split.unify
: a boolean that allows unifying the split files. Only works whenmode
ispages
.flatten
: a boolean that, when set to true, flattens the split PDF files, making form fields and annotations uneditable.
let response = try await client.convertUrl(
url: URL(string: "https://gotenberg.dev")!,
options: ChromiumOptions(
mode: .pages,
span: "1-2",
unify: true,
),
)
On the other hand, PDFEngines' has a split
function that interacts with PDF Engines split route which splits PDF files into multiple files.
let response = try await client.splitPDF(
urls: [
.init(url: "https://someurl.com/myfile.pdf")
],
options: SplitPDFOptions(
splitMode: .pages,
splitSpan: "1-2",
splitUnify: true,
),
)
⚠️ Note: Gotenberg does not currently validate thespan
value whenmode
is set topages
, as the validation depends on the chosen engine for the split feature. See PDF Engines module configuration for more details.
PDF flattening converts interactive elements like forms and annotations into a static PDF. This ensures the document looks the same everywhere and prevents further edits.
let response = try await client.flattenPDF(
urls: [
.init(url: "https://someurl.com/myfile.pdf")
]
)
client.writeToFile
is just a complementary function that takes the GotenbergResponse
returned by any functions beside readPDFMetadata, and a
chosen filepath
with name to generate a PDF file or zip file. Note that note that this function will not create sub directories if not already exist.