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=7100Create 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.
ChromiumOptionsIn 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.
ScreenshotOptionsThe 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 :
LibreOfficeConversionOptionsNote: 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 bepagesorintervals.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 whenmodeispages.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 thespanvalue whenmodeis 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.