mirror of
https://github.com/gotenberg/gotenberg.git
synced 2026-08-08 00:22:14 +01:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c1699df6c | ||
|
|
404535c512 | ||
|
|
2cedcecc38 | ||
|
|
ba7b02d8d4 | ||
|
|
6aa3c16646 | ||
|
|
5a03e17e00 | ||
|
|
417d145b43 | ||
|
|
e5636a2afa | ||
|
|
5291d2d129 | ||
|
|
c6f6a87499 | ||
|
|
1ef21c6ed6 | ||
|
|
6ee1932cbf | ||
|
|
83cf43a314 | ||
|
|
52c14a79a1 | ||
|
|
152db0551d | ||
|
|
3a2467ccfe | ||
|
|
5a28f3597c | ||
|
|
9ce179f91b |
@@ -11,13 +11,15 @@ env:
|
||||
- secure: CmLh169xwt3OC7l19lDUwdZYfw+l/+XXKjTGxnuJiXHa9hAH+nc4mEUSmqHMHwjquyYE6LnSVGZ94LH8sCaGed/TMm0Lj3DZtZ0VsjYu3sKsNrVJn5WdYEah+GvNJ8i8uzvHnGk1L2fAagLpXFUB2K9UraA1CFiHs1fF5Fua7Ra0mE7lMz0MFvyvzcmc9u8nMz71K2YVsXqn+I/rv8onJCTtc/Ds0hVrBXwG5Fh0T3xHqjOhME9ZI2hRHnnQVdBojSY3USifQ//qAKowfBVc0pebEtgFpyXx/I17A6xCm0KVtnA2tNqu1+XFkjWaBzryaLE9ujhJcTRC/YK0JUZ+QxfYbD5C7jVy9Jlx1lOEjJ42B/ImNxPP+9p3wi2MWNbcbZJPxIe635fnT17lI7CLK2Qg1xjfTQ4WTEKW5IhnYMiyfRKiripFh4PCkDm8cJlTbpntsX1n0uheydbsgf/11vS7o1WGhVQ8+Jelc4DvIbBHCqienQEOLJDBwm7FiK5JbwZJ6ZAGeDM/IhGU1h9PNjVbHUyJhUxYoPYUE9QsZFT7ENCrRQpq49KOzXBRfffyJNJRh+Ep9X5YoW0dUp0MNu5B7z2+6w9X9n/C+loa11xF42bFzniCvvbSOQ37J+EngDinVxJkNPeyivR4fye2ENhIAjAEjouTJLOSXL9nAOU=
|
||||
|
||||
stages:
|
||||
- lint
|
||||
- tests
|
||||
- publish
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- stage: lint
|
||||
- stage: tests
|
||||
script: make lint
|
||||
- stage: tests
|
||||
script: make tests
|
||||
- stage: publish
|
||||
if: tag IS present
|
||||
script: ./scripts/publish.sh $TRAVIS_TAG $DOCKER_USER $DOCKER_PASS
|
||||
@@ -11,11 +11,11 @@ At TheCodingMachine, we build a lot of web applications (intranets, extranets an
|
||||
## Features
|
||||
|
||||
* HTML and Markdown conversions using Google Chrome headless
|
||||
* Office conversions (.docx, .doc, .odt, .pptx, .ppt, .odp and so on) using [unoconv](https://github.com/dagwieers/unoconv)
|
||||
* Office conversions (.txt, .rtf, .docx, .doc, .odt, .pptx, .ppt, .odp and so on) using [unoconv](https://github.com/dagwieers/unoconv)
|
||||
* Performance :zap:: Google Chrome and Libreoffice (unoconv) started once in the background thanks to PM2
|
||||
* Failure prevention :broken_heart:: PM2 automatically restarts previous processes if they fail
|
||||
* Assets :package:: send your header, footer, images, fonts, stylesheets and so on for converting your HTML and Markdown to beaufitul PDFs!
|
||||
* Easily interact with the API using our [Go](/pkg) and [PHP](https://github.com/thecodingmachine/gotenberg-php-client) (**WIP**) libraries
|
||||
* Easily interact with the API using our [Go](/pkg) and [PHP](https://github.com/thecodingmachine/gotenberg-php-client) libraries
|
||||
|
||||
## Quick start
|
||||
|
||||
@@ -34,7 +34,7 @@ to learn how to interact with it!
|
||||
|
||||
[](https://microbadger.com/images/thecodingmachine/gotenberg:3)
|
||||
[](https://travis-ci.org/thecodingmachine/gotenberg)
|
||||
[](https://godoc.org/github.com/thecodingmachine/gotenberg?status.svg)
|
||||
[](https://godoc.org/github.com/thecodingmachine/gotenberg)
|
||||
[](https://goreportcard.com/report/thecodingmachine/gotenberg)
|
||||
|
||||
---
|
||||
|
||||
@@ -11,7 +11,7 @@ LABEL authors="Julien Neuhart <j.neuhart@thecodingmachine.com>"
|
||||
|
||||
RUN echo "deb http://httpredir.debian.org/debian/ stretch main contrib non-free" > /etc/apt/sources.list &&\
|
||||
apt-get update &&\
|
||||
apt-get install -y curl wget
|
||||
apt-get install -y curl wget python3-pip
|
||||
|
||||
# |--------------------------------------------------------------------------
|
||||
# | PM2
|
||||
@@ -39,7 +39,10 @@ RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add
|
||||
# | Unoconv
|
||||
# |--------------------------------------------------------------------------
|
||||
# |
|
||||
# | Installs MS fonts and unoconv for Office documents conversions.
|
||||
# | Installs unoconv and LibreOffice for Office documents conversions.
|
||||
# |
|
||||
|
||||
RUN apt-get -y install ttf-mscorefonts-installer unoconv
|
||||
RUN pip3 install unoconv &&\
|
||||
# https://github.com/nextcloud/docker/issues/380
|
||||
mkdir -p /usr/share/man/man1mkdir -p /usr/share/man/man1 &&\
|
||||
apt-get -y install libreoffice
|
||||
@@ -5,7 +5,7 @@ title: Introduction
|
||||
[Gotenberg](https://github.com/thecodingmachine/gotenberg/) is a Docker-powered stateless API for converting HTML, Markdown and Office documents to PDF.
|
||||
|
||||
* HTML and Markdown conversions using Google Chrome headless
|
||||
* Office conversions (.docx, .doc, .odt, .pptx, .ppt, .odp and so on) using [unoconv](https://github.com/dagwieers/unoconv)
|
||||
* Office conversions (.txt, .rtf, .docx, .doc, .odt, .pptx, .ppt, .odp and so on) using [unoconv](https://github.com/dagwieers/unoconv)
|
||||
* Performance: Google Chrome and Libreoffice (unoconv) started once in the background thanks to PM2
|
||||
* Failure prevention: PM2 automatically restarts previous processes if they fail
|
||||
* Assets: send your header, footer, images, fonts, stylesheets and so on for converting your HTML and Markdown to beaufitul PDFs!
|
||||
|
||||
@@ -26,13 +26,13 @@ For instance:
|
||||
</html>
|
||||
```
|
||||
|
||||
### Guzzle
|
||||
### cURL
|
||||
|
||||
```bash
|
||||
$ curl --request POST \
|
||||
--url http://localhost:3000/convert/html \
|
||||
--header 'Content-Type: multipart/form-data' \
|
||||
--form files=@index.html
|
||||
--form files=@index.html \
|
||||
> result.pdf
|
||||
```
|
||||
|
||||
@@ -43,9 +43,7 @@ import "github.com/thecodingmachine/gotenberg/pkg"
|
||||
|
||||
func main() {
|
||||
c := &gotenberg.Client{Hostname: "http://localhost:3000"}
|
||||
req := &gotenberg.HTMLRequest{
|
||||
IndexFilePath: "index.html",
|
||||
}
|
||||
req, _ := gotenberg.NewHTMLRequest("index.html")
|
||||
dest := "result.pdf"
|
||||
c.Store(req, dest)
|
||||
}
|
||||
@@ -53,7 +51,17 @@ func main() {
|
||||
|
||||
### PHP
|
||||
|
||||
TODO
|
||||
```php
|
||||
use TheCodingMachine\Gotenberg\Client;
|
||||
use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
use TheCodingMachine\Gotenberg\HTMLRequest;
|
||||
|
||||
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
$request = new HTMLRequest($index);
|
||||
$dirPath = "/foo";
|
||||
$filename = $client->store($request, $dirPath);
|
||||
```
|
||||
|
||||
## Header and footer
|
||||
|
||||
@@ -90,15 +98,15 @@ The following classes allow you to inject printing values:
|
||||
> **Attention:** the CSS properties are independant of the ones used in the `index.html` file.
|
||||
> Also, `footer.html` CSS properties override the ones from `header.html`.
|
||||
|
||||
### Guzzle
|
||||
### cURL
|
||||
|
||||
```bash
|
||||
$ curl --request POST \
|
||||
--url http://localhost:3000/convert/html \
|
||||
--header 'Content-Type: multipart/form-data' \
|
||||
--form files=@index.html
|
||||
--form files=@header.html
|
||||
--form files=@footer.html
|
||||
--form files=@index.html \
|
||||
--form files=@header.html \
|
||||
--form files=@footer.html \
|
||||
> result.pdf
|
||||
```
|
||||
|
||||
@@ -109,13 +117,9 @@ import "github.com/thecodingmachine/gotenberg/pkg"
|
||||
|
||||
func main() {
|
||||
c := &gotenberg.Client{Hostname: "http://localhost:3000"}
|
||||
req := &gotenberg.HTMLRequest{
|
||||
IndexFilePath: "index.html",
|
||||
Options: &gotenberg.HTMLOptions{
|
||||
HeaderFilePath: "header.html",
|
||||
FooterFilePath: "footer.html",
|
||||
},
|
||||
}
|
||||
req, _ := gotenberg.NewHTMLRequest("index.html")
|
||||
req.SetHeader("header.html")
|
||||
req.SetFooter("footer.html")
|
||||
dest := "result.pdf"
|
||||
c.Store(req, dest)
|
||||
}
|
||||
@@ -123,11 +127,25 @@ func main() {
|
||||
|
||||
### PHP
|
||||
|
||||
TODO
|
||||
```php
|
||||
use TheCodingMachine\Gotenberg\Client;
|
||||
use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
use TheCodingMachine\Gotenberg\HTMLRequest;
|
||||
|
||||
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
$header = DocumentFactory::makeFromPath('header.html', 'header.html');
|
||||
$footer = DocumentFactory::makeFromPath('footer.html', 'footer.html');
|
||||
$request = new HTMLRequest($index);
|
||||
$request->setHeader($header);
|
||||
$request->setFooter($footer);
|
||||
$dirPath = "/foo";
|
||||
$filename = $client->store($request, $dirPath);
|
||||
```
|
||||
|
||||
## Assets
|
||||
|
||||
You may also send additional files. For instance, images, fonts, stylesheets and so on.
|
||||
You may also send additional files. For instance: images, fonts, stylesheets and so on.
|
||||
|
||||
The only requirement is to make sure that their paths
|
||||
are on the same level as the `index.html` file.
|
||||
@@ -169,16 +187,16 @@ You may also use *remote* paths for Google fonts, images and so on.
|
||||
> If you want to install fonts directly in the Gotenberg Docker image,
|
||||
> see to the [fonts section](#office.fonts).
|
||||
|
||||
### Guzzle
|
||||
### cURL
|
||||
|
||||
```bash
|
||||
$ curl --request POST \
|
||||
--url http://localhost:3000/convert/html \
|
||||
--header 'Content-Type: multipart/form-data' \
|
||||
--form files=@index.html
|
||||
--form files=@style.css
|
||||
--form files=@img.png
|
||||
--form files=@font.woff
|
||||
--form files=@index.html \
|
||||
--form files=@style.css \
|
||||
--form files=@img.png \
|
||||
--form files=@font.woff \
|
||||
> result.pdf
|
||||
```
|
||||
|
||||
@@ -189,14 +207,12 @@ import "github.com/thecodingmachine/gotenberg/pkg"
|
||||
|
||||
func main() {
|
||||
c := &gotenberg.Client{Hostname: "http://localhost:3000"}
|
||||
req := &gotenberg.HTMLRequest{
|
||||
IndexFilePath: "index.html",
|
||||
AssetFilePaths: []string{
|
||||
"style.css",
|
||||
"img.png",
|
||||
"font.woff",
|
||||
},
|
||||
}
|
||||
req, _ := gotenberg.NewHTMLRequest("index.html")
|
||||
req.SetAssets([]string{
|
||||
"font.woff",
|
||||
"img.gif",
|
||||
"style.css",
|
||||
})
|
||||
dest := "result.pdf"
|
||||
c.Store(req, dest)
|
||||
}
|
||||
@@ -204,31 +220,47 @@ func main() {
|
||||
|
||||
### PHP
|
||||
|
||||
TODO
|
||||
```php
|
||||
use TheCodingMachine\Gotenberg\Client;
|
||||
use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
use TheCodingMachine\Gotenberg\HTMLRequest;
|
||||
|
||||
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
$assets = [
|
||||
DocumentFactory::makeFromPath('style.css', 'style.css'),
|
||||
DocumentFactory::makeFromPath('img.png', 'img.png'),
|
||||
DocumentFactory::makeFromPath('font.woff', 'font.woff'),
|
||||
];
|
||||
$request = new HTMLRequest($index);
|
||||
$request->setAssets($assets);
|
||||
$dirPath = "/foo";
|
||||
$filename = $client->store($request, $dirPath);
|
||||
```
|
||||
|
||||
## Paper size, margins, orientation
|
||||
|
||||
You may also customize the resulting PDF paper.
|
||||
You may also customize the resulting PDF format.
|
||||
|
||||
By default, it will be rendered in `A4` size with `1 inch` margins and `portrait` orientation.
|
||||
By default, it will be rendered with `A4` size, `1 inch` margins and `portrait` orientation.
|
||||
|
||||
> Paper size and margins have to be provided in `inches`.
|
||||
> Also, you have to set both `paperWidth` and `paperHeight`. Same for margins.
|
||||
|
||||
### Guzzle
|
||||
### cURL
|
||||
|
||||
```bash
|
||||
$ curl --request POST \
|
||||
--url http://localhost:3000/convert/html \
|
||||
--header 'Content-Type: multipart/form-data' \
|
||||
--form files=@index.html
|
||||
--form paperWidth=8.27
|
||||
--form paperHeight=11.27
|
||||
--form marginTop=0
|
||||
--form marginBottom=0
|
||||
--form marginLeft=0
|
||||
--form marginRight=0
|
||||
--form landscape=true
|
||||
--form files=@index.html \
|
||||
--form paperWidth=8.27 \
|
||||
--form paperHeight=11.27 \
|
||||
--form marginTop=0 \
|
||||
--form marginBottom=0 \
|
||||
--form marginLeft=0 \
|
||||
--form marginRight=0 \
|
||||
--form landscape=true \
|
||||
> result.pdf
|
||||
```
|
||||
|
||||
@@ -239,14 +271,10 @@ import "github.com/thecodingmachine/gotenberg/pkg"
|
||||
|
||||
func main() {
|
||||
c := &gotenberg.Client{Hostname: "http://localhost:3000"}
|
||||
req := &gotenberg.HTMLRequest{
|
||||
IndexFilePath: "index.html",
|
||||
Options: &gotenberg.HTMLOptions{
|
||||
PaperSize: gotenberg.A4,
|
||||
PaperMargins: gotenberg.NoMargins,
|
||||
Landscape: true
|
||||
},
|
||||
}
|
||||
req, _ := gotenberg.NewHTMLRequest("index.html")
|
||||
req.SetPaperSize(gotenberg.A4)
|
||||
req.SetMargins(gotenberg.NoMargins)
|
||||
req.SetLandscape(true)
|
||||
dest := "result.pdf"
|
||||
c.Store(req, dest)
|
||||
}
|
||||
@@ -254,4 +282,18 @@ func main() {
|
||||
|
||||
### PHP
|
||||
|
||||
TODO
|
||||
```php
|
||||
use TheCodingMachine\Gotenberg\Client;
|
||||
use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
use TheCodingMachine\Gotenberg\HTMLRequest;
|
||||
use TheCodingMachine\Gotenberg\Request;
|
||||
|
||||
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
$request = new HTMLRequest($index);
|
||||
$request->setPaperSize(Request::A4);
|
||||
$request->setMargins(Request::NO_MARGINS);
|
||||
$request->setLandscape(true);
|
||||
$dirPath = "/foo";
|
||||
$filename = $client->store($request, $dirPath);
|
||||
```
|
||||
@@ -11,7 +11,7 @@ It accepts `POST` requests with a `multipart/form-data` Content-Type.
|
||||
Markdown conversions work the same as HTML conversions.
|
||||
|
||||
Only difference is that you have access to the Go template function `toHTML`
|
||||
in the file `index.html` which will convert a given markdown file to HTML.
|
||||
in the file `index.html`. This function will convert a given markdown file to HTML.
|
||||
|
||||
For instance:
|
||||
|
||||
@@ -28,14 +28,14 @@ For instance:
|
||||
</html>
|
||||
```
|
||||
|
||||
### Guzzle
|
||||
### cURL
|
||||
|
||||
```bash
|
||||
$ curl --request POST \
|
||||
--url http://localhost:3000/convert/markdown \
|
||||
--header 'Content-Type: multipart/form-data' \
|
||||
--form files=@index.html
|
||||
--form files=@file.md
|
||||
--form files=@index.html \
|
||||
--form files=@file.md \
|
||||
> result.pdf
|
||||
```
|
||||
|
||||
@@ -46,12 +46,7 @@ import "github.com/thecodingmachine/gotenberg/pkg"
|
||||
|
||||
func main() {
|
||||
c := &gotenberg.Client{Hostname: "http://localhost:3000"}
|
||||
req := &gotenberg.MarkdownRequest{
|
||||
IndexFilePath: "index.html",
|
||||
MarkdownFilePaths: []string{
|
||||
"file.md",
|
||||
},
|
||||
}
|
||||
req, _ := gotenberg.NewMarkdownRequest("index.html", []string{"file.md"})
|
||||
dest := "result.pdf"
|
||||
c.Store(req, dest)
|
||||
}
|
||||
@@ -59,4 +54,17 @@ func main() {
|
||||
|
||||
### PHP
|
||||
|
||||
TODO
|
||||
```php
|
||||
use TheCodingMachine\Gotenberg\Client;
|
||||
use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
use TheCodingMachine\Gotenberg\MarkdownRequest;
|
||||
|
||||
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
$markdowns = [
|
||||
DocumentFactory::makeFromPath('file.md', 'file.md'),
|
||||
];
|
||||
$request = new MarkdownRequest($index, $markdowns);
|
||||
$dirPath = "/foo";
|
||||
$filename = $client->store($request, $dirPath);
|
||||
```
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
title: Office
|
||||
---
|
||||
|
||||
Gotenberg provides the endpoint `/convert/office` for Office documents conversions.
|
||||
Gotenberg provides the endpoint `/convert/office` for Office document conversions.
|
||||
|
||||
It accepts `POST` requests with a `multipart/form-data` Content-Type.
|
||||
|
||||
@@ -10,6 +10,8 @@ It accepts `POST` requests with a `multipart/form-data` Content-Type.
|
||||
|
||||
You may send one or more Office documents. Following file extensions are accepted:
|
||||
|
||||
* `.txt`
|
||||
* `.rtf`
|
||||
* `.doc`
|
||||
* `.docx`
|
||||
* `.odt`
|
||||
@@ -26,14 +28,14 @@ All files will be merged into a single resulting PDF.
|
||||
> That's why for Office conversions, the API does only one conversion at a time.
|
||||
> See the [scalability section](#scalability) to find how to mitigate this issue.
|
||||
|
||||
### Guzzle
|
||||
### cURL
|
||||
|
||||
```bash
|
||||
$ curl --request POST \
|
||||
--url http://localhost:3000/convert/office \
|
||||
--header 'Content-Type: multipart/form-data' \
|
||||
--form files=@document.docx
|
||||
--form files=@document2.docx
|
||||
--form files=@document.docx \
|
||||
--form files=@document2.docx \
|
||||
> result.pdf
|
||||
```
|
||||
|
||||
@@ -44,12 +46,7 @@ import "github.com/thecodingmachine/gotenberg/pkg"
|
||||
|
||||
func main() {
|
||||
c := &gotenberg.Client{Hostname: "http://localhost:3000"}
|
||||
req := &gotenberg.OfficeRequest{
|
||||
FilePaths: []string{
|
||||
"document.docx",
|
||||
"document2.docx",
|
||||
},
|
||||
}
|
||||
req, _ := gotenberg.NewOfficeRequest([]string{"document.docx", "document2.docx"})
|
||||
dest := "result.pdf"
|
||||
c.Store(req, dest)
|
||||
}
|
||||
@@ -57,7 +54,75 @@ func main() {
|
||||
|
||||
### PHP
|
||||
|
||||
TODO
|
||||
```php
|
||||
use TheCodingMachine\Gotenberg\Client;
|
||||
use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
use TheCodingMachine\Gotenberg\OfficeRequest;
|
||||
|
||||
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
$files = [
|
||||
DocumentFactory::makeFromPath('document.docx', 'document.docx'),
|
||||
DocumentFactory::makeFromPath('document2.docx', 'document2.docx'),
|
||||
];
|
||||
$request = new OfficeRequest($files);
|
||||
$dirPath = "/foo";
|
||||
$filename = $client->store($request, $dirPath);
|
||||
```
|
||||
|
||||
## Paper size and orientation
|
||||
|
||||
You may also customize the resulting PDF format.
|
||||
|
||||
By default, it will be rendered with `A4` size and `portrait` orientation.
|
||||
|
||||
> Paper size has to be provided in `inches`.
|
||||
> Also, you have to set both `paperWidth` and `paperHeight`.
|
||||
|
||||
### cURL
|
||||
|
||||
```bash
|
||||
$ curl --request POST \
|
||||
--url http://localhost:3000/convert/office \
|
||||
--header 'Content-Type: multipart/form-data' \
|
||||
--form files=@document.docx \
|
||||
--form paperWidth=8.27 \
|
||||
--form paperHeight=11.27 \
|
||||
--form landscape=true \
|
||||
> result.pdf
|
||||
```
|
||||
|
||||
### Go
|
||||
|
||||
```golang
|
||||
import "github.com/thecodingmachine/gotenberg/pkg"
|
||||
|
||||
func main() {
|
||||
c := &gotenberg.Client{Hostname: "http://localhost:3000"}
|
||||
req, _ := gotenberg.NewOfficeRequest([]string{"document.docx"})
|
||||
req.SetPaperSize(gotenberg.A4)
|
||||
req.SetLandscape(true)
|
||||
dest := "result.pdf"
|
||||
c.Store(req, dest)
|
||||
}
|
||||
```
|
||||
|
||||
### PHP
|
||||
|
||||
```php
|
||||
use TheCodingMachine\Gotenberg\Client;
|
||||
use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
use TheCodingMachine\Gotenberg\OfficeRequest;
|
||||
|
||||
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
$files = [
|
||||
DocumentFactory::makeFromPath('document.docx', 'document.docx'),
|
||||
];
|
||||
$request = new OfficeRequest($files);
|
||||
$request->setPaperSize(Request::A4);
|
||||
$request->setLandscape(true);
|
||||
$dirPath = "/foo";
|
||||
$filename = $client->store($request, $dirPath);
|
||||
```
|
||||
|
||||
## Fonts
|
||||
|
||||
|
||||
@@ -11,14 +11,14 @@ It accepts `POST` requests with a `multipart/form-data` Content-Type.
|
||||
Nothing special here: you may send one or more PDF files and the API
|
||||
will merge them and return the resulting PDF file.
|
||||
|
||||
### Guzzle
|
||||
### cURL
|
||||
|
||||
```bash
|
||||
$ curl --request POST \
|
||||
--url http://localhost:3000/merge \
|
||||
--header 'Content-Type: multipart/form-data' \
|
||||
--form files=@file.pdf
|
||||
--form files=@file2.pdf
|
||||
--form files=@file.pdf \
|
||||
--form files=@file2.pdf \
|
||||
> result.pdf
|
||||
```
|
||||
|
||||
@@ -29,12 +29,7 @@ import "github.com/thecodingmachine/gotenberg/pkg"
|
||||
|
||||
func main() {
|
||||
c := &gotenberg.Client{Hostname: "http://localhost:3000"}
|
||||
req := &gotenberg.MergeRequest{
|
||||
FilePaths: []string{
|
||||
"file.pdf",
|
||||
"file2.pdf",
|
||||
},
|
||||
}
|
||||
req, _ := gotenberg.NewMergeRequest([]string{"file.pdf", "file2.pdf"})
|
||||
dest := "result.pdf"
|
||||
c.Store(req, dest)
|
||||
}
|
||||
@@ -42,4 +37,17 @@ func main() {
|
||||
|
||||
### PHP
|
||||
|
||||
TODO
|
||||
```php
|
||||
use TheCodingMachine\Gotenberg\Client;
|
||||
use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
use TheCodingMachine\Gotenberg\MergeRequest;
|
||||
|
||||
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
$files = [
|
||||
DocumentFactory::makeFromPath('file.pdf', 'file.pdf'),
|
||||
DocumentFactory::makeFromPath('file2.pdf', 'file2.pdf'),
|
||||
];
|
||||
$request = new MergeRequest($files);
|
||||
$dirPath = "/foo";
|
||||
$filename = $client->store($request, $dirPath);
|
||||
```
|
||||
@@ -7,19 +7,18 @@ All endpoints accept a form field named `webhookURL`.
|
||||
If provided, the API will send the resulting PDF file in a `POST` request with the `application/pdf` Content-Type
|
||||
to given URL.
|
||||
|
||||
By doing so, your requests to the API will be done before the conversions are actually done!
|
||||
By doing so, your requests to the API will be over before the conversions are actually done!
|
||||
|
||||
## Examples
|
||||
|
||||
### Guzzle
|
||||
### cURL
|
||||
|
||||
```bash
|
||||
$ curl --request POST \
|
||||
--url http://localhost:3000/convert/html \
|
||||
--header 'Content-Type: multipart/form-data' \
|
||||
--form files=@index.html
|
||||
--form files=@index.html \
|
||||
--form webhookURL='http://myapp.com/webhook/'
|
||||
> result.pdf
|
||||
```
|
||||
|
||||
### Go
|
||||
@@ -29,17 +28,23 @@ import "github.com/thecodingmachine/gotenberg/pkg"
|
||||
|
||||
func main() {
|
||||
c := &gotenberg.Client{Hostname: "http://localhost:3000"}
|
||||
req := &gotenberg.HTMLRequest{
|
||||
IndexFilePath: "index.html",
|
||||
Options: &gotenberg.HTMLOptions{
|
||||
WebHookURL: "http://myapp.com/webhook/",
|
||||
},
|
||||
}
|
||||
req, _ := gotenberg.NewHTMLRequest("index.html")
|
||||
req.SetWebhookURL("http://myapp.com/webhook/")
|
||||
dest := "result.pdf"
|
||||
resp, err := c.Post(req)
|
||||
resp, _ := c.Post(req)
|
||||
}
|
||||
```
|
||||
|
||||
### PHP
|
||||
|
||||
TODO
|
||||
```php
|
||||
use TheCodingMachine\Gotenberg\Client;
|
||||
use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
use TheCodingMachine\Gotenberg\HTMLRequest;
|
||||
|
||||
$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
$request = new HTMLRequest($index);
|
||||
$request->setWebhookURL('http://myapp.com/webhook/');
|
||||
$resp = $client->post($request);
|
||||
```
|
||||
@@ -21,4 +21,5 @@ go test github.com/thecodingmachine/gotenberg/internal/pkg/pm2 -run TestUnoconvS
|
||||
go build -o /usr/local/bin/gotenberg cmd/gotenberg/main.go
|
||||
gotenberg &
|
||||
sleep 10
|
||||
go test -race -cover -covermode=atomic github.com/thecodingmachine/gotenberg/pkg
|
||||
go test -race -cover -covermode=atomic github.com/thecodingmachine/gotenberg/pkg
|
||||
sleep 5 # allows Gotenberg to remove generated files (concurrent requests).
|
||||
355
docs/index.html
355
docs/index.html
@@ -71,7 +71,7 @@
|
||||
|
||||
<ul>
|
||||
<li>HTML and Markdown conversions using Google Chrome headless</li>
|
||||
<li>Office conversions (.docx, .doc, .odt, .pptx, .ppt, .odp and so on) using <a href="https://github.com/dagwieers/unoconv">unoconv</a></li>
|
||||
<li>Office conversions (.txt, .rtf, .docx, .doc, .odt, .pptx, .ppt, .odp and so on) using <a href="https://github.com/dagwieers/unoconv">unoconv</a></li>
|
||||
<li>Performance: Google Chrome and Libreoffice (unoconv) started once in the background thanks to PM2</li>
|
||||
<li>Failure prevention: PM2 automatically restarts previous processes if they fail</li>
|
||||
<li>Assets: send your header, footer, images, fonts, stylesheets and so on for converting your HTML and Markdown to beaufitul PDFs!</li>
|
||||
@@ -168,15 +168,15 @@ which will be converted to PDF.</p>
|
||||
<span class="p"><</span><span class="p">/</span><span class="nt">html</span><span class="p">></span>
|
||||
</pre>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="html.basic.guzzle" href="#html.basic.guzzle">
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="html.basic.c_url" href="#html.basic.c_url">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Guzzle</h3>
|
||||
</a>cURL</h3>
|
||||
|
||||
<pre class="chroma">$ curl --request POST <span class="se">\
|
||||
</span><span class="se"></span> --url http://localhost:3000/convert/html <span class="se">\
|
||||
</span><span class="se"></span> --header <span class="s1">'Content-Type: multipart/form-data'</span> <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@index.html
|
||||
> result.pdf
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@index.html <span class="se">\
|
||||
</span><span class="se"></span> > result.pdf
|
||||
</pre>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="html.basic.go" href="#html.basic.go">
|
||||
@@ -187,9 +187,7 @@ which will be converted to PDF.</p>
|
||||
|
||||
<span class="kd">func</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="nx">c</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">Client</span><span class="p">{</span><span class="nx">Hostname</span><span class="p">:</span> <span class="s">"http://localhost:3000"</span><span class="p">}</span>
|
||||
<span class="nx">req</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">HTMLRequest</span><span class="p">{</span>
|
||||
<span class="nx">IndexFilePath</span><span class="p">:</span> <span class="s">"index.html"</span><span class="p">,</span>
|
||||
<span class="p">}</span>
|
||||
<span class="nx">req</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">gotenberg</span><span class="p">.</span><span class="nx">NewHTMLRequest</span><span class="p">(</span><span class="s">"index.html"</span><span class="p">)</span>
|
||||
<span class="nx">dest</span> <span class="o">:=</span> <span class="s">"result.pdf"</span>
|
||||
<span class="nx">c</span><span class="p">.</span><span class="nx">Store</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">dest</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
@@ -199,7 +197,16 @@ which will be converted to PDF.</p>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>PHP</h3>
|
||||
|
||||
<p>TODO</p>
|
||||
<pre class="chroma"><span class="x">use TheCodingMachine\Gotenberg\Client;
|
||||
</span><span class="x">use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
</span><span class="x">use TheCodingMachine\Gotenberg\HTMLRequest;
|
||||
</span><span class="x">
|
||||
</span><span class="x">$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
</span><span class="x">$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
</span><span class="x">$request = new HTMLRequest($index);
|
||||
</span><span class="x">$dirPath = "/foo";
|
||||
</span><span class="x">$filename = $client->store($request, $dirPath);
|
||||
</span><span class="x"></span></pre>
|
||||
|
||||
<h2 class="Heading"><a class="Anchor" aria-hidden="true" id="html.header_and_footer" href="#html.header_and_footer">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
@@ -241,17 +248,17 @@ Respectively, a file named <code>header.html</code> and <code>footer.html</code>
|
||||
Also, <code>footer.html</code> CSS properties override the ones from <code>header.html</code>.</p>
|
||||
</blockquote>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="html.header_and_footer.guzzle" href="#html.header_and_footer.guzzle">
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="html.header_and_footer.c_url" href="#html.header_and_footer.c_url">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Guzzle</h3>
|
||||
</a>cURL</h3>
|
||||
|
||||
<pre class="chroma">$ curl --request POST <span class="se">\
|
||||
</span><span class="se"></span> --url http://localhost:3000/convert/html <span class="se">\
|
||||
</span><span class="se"></span> --header <span class="s1">'Content-Type: multipart/form-data'</span> <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@index.html
|
||||
--form <span class="nv">files</span><span class="o">=</span>@header.html
|
||||
--form <span class="nv">files</span><span class="o">=</span>@footer.html
|
||||
> result.pdf
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@index.html <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@header.html <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@footer.html <span class="se">\
|
||||
</span><span class="se"></span> > result.pdf
|
||||
</pre>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="html.header_and_footer.go" href="#html.header_and_footer.go">
|
||||
@@ -262,13 +269,9 @@ Also, <code>footer.html</code> CSS properties override the ones from <code>heade
|
||||
|
||||
<span class="kd">func</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="nx">c</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">Client</span><span class="p">{</span><span class="nx">Hostname</span><span class="p">:</span> <span class="s">"http://localhost:3000"</span><span class="p">}</span>
|
||||
<span class="nx">req</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">HTMLRequest</span><span class="p">{</span>
|
||||
<span class="nx">IndexFilePath</span><span class="p">:</span> <span class="s">"index.html"</span><span class="p">,</span>
|
||||
<span class="nx">Options</span><span class="p">:</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">HTMLOptions</span><span class="p">{</span>
|
||||
<span class="nx">HeaderFilePath</span><span class="p">:</span> <span class="s">"header.html"</span><span class="p">,</span>
|
||||
<span class="nx">FooterFilePath</span><span class="p">:</span> <span class="s">"footer.html"</span><span class="p">,</span>
|
||||
<span class="p">},</span>
|
||||
<span class="p">}</span>
|
||||
<span class="nx">req</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">gotenberg</span><span class="p">.</span><span class="nx">NewHTMLRequest</span><span class="p">(</span><span class="s">"index.html"</span><span class="p">)</span>
|
||||
<span class="nx">req</span><span class="p">.</span><span class="nx">SetHeader</span><span class="p">(</span><span class="s">"header.html"</span><span class="p">)</span>
|
||||
<span class="nx">req</span><span class="p">.</span><span class="nx">SetFooter</span><span class="p">(</span><span class="s">"footer.html"</span><span class="p">)</span>
|
||||
<span class="nx">dest</span> <span class="o">:=</span> <span class="s">"result.pdf"</span>
|
||||
<span class="nx">c</span><span class="p">.</span><span class="nx">Store</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">dest</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
@@ -278,13 +281,26 @@ Also, <code>footer.html</code> CSS properties override the ones from <code>heade
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>PHP</h3>
|
||||
|
||||
<p>TODO</p>
|
||||
<pre class="chroma"><span class="x">use TheCodingMachine\Gotenberg\Client;
|
||||
</span><span class="x">use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
</span><span class="x">use TheCodingMachine\Gotenberg\HTMLRequest;
|
||||
</span><span class="x">
|
||||
</span><span class="x">$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
</span><span class="x">$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
</span><span class="x">$header = DocumentFactory::makeFromPath('header.html', 'header.html');
|
||||
</span><span class="x">$footer = DocumentFactory::makeFromPath('footer.html', 'footer.html');
|
||||
</span><span class="x">$request = new HTMLRequest($index);
|
||||
</span><span class="x">$request->setHeader($header);
|
||||
</span><span class="x">$request->setFooter($footer);
|
||||
</span><span class="x">$dirPath = "/foo";
|
||||
</span><span class="x">$filename = $client->store($request, $dirPath);
|
||||
</span><span class="x"></span></pre>
|
||||
|
||||
<h2 class="Heading"><a class="Anchor" aria-hidden="true" id="html.assets" href="#html.assets">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Assets</h2>
|
||||
|
||||
<p>You may also send additional files. For instance, images, fonts, stylesheets and so on.</p>
|
||||
<p>You may also send additional files. For instance: images, fonts, stylesheets and so on.</p>
|
||||
|
||||
<p>The only requirement is to make sure that their paths
|
||||
are on the same level as the <code>index.html</code> file.</p>
|
||||
@@ -326,18 +342,18 @@ are on the same level as the <code>index.html</code> file.</p>
|
||||
see to the <a href="#office.fonts">fonts section</a>.</p>
|
||||
</blockquote>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="html.assets.guzzle" href="#html.assets.guzzle">
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="html.assets.c_url" href="#html.assets.c_url">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Guzzle</h3>
|
||||
</a>cURL</h3>
|
||||
|
||||
<pre class="chroma">$ curl --request POST <span class="se">\
|
||||
</span><span class="se"></span> --url http://localhost:3000/convert/html <span class="se">\
|
||||
</span><span class="se"></span> --header <span class="s1">'Content-Type: multipart/form-data'</span> <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@index.html
|
||||
--form <span class="nv">files</span><span class="o">=</span>@style.css
|
||||
--form <span class="nv">files</span><span class="o">=</span>@img.png
|
||||
--form <span class="nv">files</span><span class="o">=</span>@font.woff
|
||||
> result.pdf
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@index.html <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@style.css <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@img.png <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@font.woff <span class="se">\
|
||||
</span><span class="se"></span> > result.pdf
|
||||
</pre>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="html.assets.go" href="#html.assets.go">
|
||||
@@ -348,14 +364,12 @@ see to the <a href="#office.fonts">fonts section</a>.</p>
|
||||
|
||||
<span class="kd">func</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="nx">c</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">Client</span><span class="p">{</span><span class="nx">Hostname</span><span class="p">:</span> <span class="s">"http://localhost:3000"</span><span class="p">}</span>
|
||||
<span class="nx">req</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">HTMLRequest</span><span class="p">{</span>
|
||||
<span class="nx">IndexFilePath</span><span class="p">:</span> <span class="s">"index.html"</span><span class="p">,</span>
|
||||
<span class="nx">AssetFilePaths</span><span class="p">:</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span>
|
||||
<span class="s">"style.css"</span><span class="p">,</span>
|
||||
<span class="s">"img.png"</span><span class="p">,</span>
|
||||
<span class="s">"font.woff"</span><span class="p">,</span>
|
||||
<span class="p">},</span>
|
||||
<span class="p">}</span>
|
||||
<span class="nx">req</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">gotenberg</span><span class="p">.</span><span class="nx">NewHTMLRequest</span><span class="p">(</span><span class="s">"index.html"</span><span class="p">)</span>
|
||||
<span class="nx">req</span><span class="p">.</span><span class="nx">SetAssets</span><span class="p">([]</span><span class="kt">string</span><span class="p">{</span>
|
||||
<span class="s">"font.woff"</span><span class="p">,</span>
|
||||
<span class="s">"img.gif"</span><span class="p">,</span>
|
||||
<span class="s">"style.css"</span><span class="p">,</span>
|
||||
<span class="p">})</span>
|
||||
<span class="nx">dest</span> <span class="o">:=</span> <span class="s">"result.pdf"</span>
|
||||
<span class="nx">c</span><span class="p">.</span><span class="nx">Store</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">dest</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
@@ -365,37 +379,52 @@ see to the <a href="#office.fonts">fonts section</a>.</p>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>PHP</h3>
|
||||
|
||||
<p>TODO</p>
|
||||
<pre class="chroma"><span class="x">use TheCodingMachine\Gotenberg\Client;
|
||||
</span><span class="x">use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
</span><span class="x">use TheCodingMachine\Gotenberg\HTMLRequest;
|
||||
</span><span class="x">
|
||||
</span><span class="x">$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
</span><span class="x">$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
</span><span class="x">$assets = [
|
||||
</span><span class="x"> DocumentFactory::makeFromPath('style.css', 'style.css'),
|
||||
</span><span class="x"> DocumentFactory::makeFromPath('img.png', 'img.png'),
|
||||
</span><span class="x"> DocumentFactory::makeFromPath('font.woff', 'font.woff'),
|
||||
</span><span class="x">];
|
||||
</span><span class="x">$request = new HTMLRequest($index);
|
||||
</span><span class="x">$request->setAssets($assets);
|
||||
</span><span class="x">$dirPath = "/foo";
|
||||
</span><span class="x">$filename = $client->store($request, $dirPath);
|
||||
</span><span class="x"></span></pre>
|
||||
|
||||
<h2 class="Heading"><a class="Anchor" aria-hidden="true" id="html.paper_size_margins_orientation" href="#html.paper_size_margins_orientation">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Paper size, margins, orientation</h2>
|
||||
|
||||
<p>You may also customize the resulting PDF paper.</p>
|
||||
<p>You may also customize the resulting PDF format.</p>
|
||||
|
||||
<p>By default, it will be rendered in <code>A4</code> size with <code>1 inch</code> margins and <code>portrait</code> orientation.</p>
|
||||
<p>By default, it will be rendered with <code>A4</code> size, <code>1 inch</code> margins and <code>portrait</code> orientation.</p>
|
||||
|
||||
<blockquote>
|
||||
<p>Paper size and margins have to be provided in <code>inches</code>.
|
||||
Also, you have to set both <code>paperWidth</code> and <code>paperHeight</code>. Same for margins.</p>
|
||||
</blockquote>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="html.paper_size_margins_orientation.guzzle" href="#html.paper_size_margins_orientation.guzzle">
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="html.paper_size_margins_orientation.c_url" href="#html.paper_size_margins_orientation.c_url">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Guzzle</h3>
|
||||
</a>cURL</h3>
|
||||
|
||||
<pre class="chroma">$ curl --request POST <span class="se">\
|
||||
</span><span class="se"></span> --url http://localhost:3000/convert/html <span class="se">\
|
||||
</span><span class="se"></span> --header <span class="s1">'Content-Type: multipart/form-data'</span> <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@index.html
|
||||
--form <span class="nv">paperWidth</span><span class="o">=</span><span class="m">8</span>.27
|
||||
--form <span class="nv">paperHeight</span><span class="o">=</span><span class="m">11</span>.27
|
||||
--form <span class="nv">marginTop</span><span class="o">=</span><span class="m">0</span>
|
||||
--form <span class="nv">marginBottom</span><span class="o">=</span><span class="m">0</span>
|
||||
--form <span class="nv">marginLeft</span><span class="o">=</span><span class="m">0</span>
|
||||
--form <span class="nv">marginRight</span><span class="o">=</span><span class="m">0</span>
|
||||
--form <span class="nv">landscape</span><span class="o">=</span><span class="nb">true</span>
|
||||
> result.pdf
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@index.html <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">paperWidth</span><span class="o">=</span><span class="m">8</span>.27 <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">paperHeight</span><span class="o">=</span><span class="m">11</span>.27 <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">marginTop</span><span class="o">=</span><span class="m">0</span> <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">marginBottom</span><span class="o">=</span><span class="m">0</span> <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">marginLeft</span><span class="o">=</span><span class="m">0</span> <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">marginRight</span><span class="o">=</span><span class="m">0</span> <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">landscape</span><span class="o">=</span><span class="nb">true</span> <span class="se">\
|
||||
</span><span class="se"></span> > result.pdf
|
||||
</pre>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="html.paper_size_margins_orientation.go" href="#html.paper_size_margins_orientation.go">
|
||||
@@ -406,14 +435,10 @@ Also, you have to set both <code>paperWidth</code> and <code>paperHeight</code>.
|
||||
|
||||
<span class="kd">func</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="nx">c</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">Client</span><span class="p">{</span><span class="nx">Hostname</span><span class="p">:</span> <span class="s">"http://localhost:3000"</span><span class="p">}</span>
|
||||
<span class="nx">req</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">HTMLRequest</span><span class="p">{</span>
|
||||
<span class="nx">IndexFilePath</span><span class="p">:</span> <span class="s">"index.html"</span><span class="p">,</span>
|
||||
<span class="nx">Options</span><span class="p">:</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">HTMLOptions</span><span class="p">{</span>
|
||||
<span class="nx">PaperSize</span><span class="p">:</span> <span class="nx">gotenberg</span><span class="p">.</span><span class="nx">A4</span><span class="p">,</span>
|
||||
<span class="nx">PaperMargins</span><span class="p">:</span> <span class="nx">gotenberg</span><span class="p">.</span><span class="nx">NoMargins</span><span class="p">,</span>
|
||||
<span class="nx">Landscape</span><span class="p">:</span> <span class="kc">true</span>
|
||||
<span class="p">},</span>
|
||||
<span class="p">}</span>
|
||||
<span class="nx">req</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">gotenberg</span><span class="p">.</span><span class="nx">NewHTMLRequest</span><span class="p">(</span><span class="s">"index.html"</span><span class="p">)</span>
|
||||
<span class="nx">req</span><span class="p">.</span><span class="nx">SetPaperSize</span><span class="p">(</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">A4</span><span class="p">)</span>
|
||||
<span class="nx">req</span><span class="p">.</span><span class="nx">SetMargins</span><span class="p">(</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">NoMargins</span><span class="p">)</span>
|
||||
<span class="nx">req</span><span class="p">.</span><span class="nx">SetLandscape</span><span class="p">(</span><span class="kc">true</span><span class="p">)</span>
|
||||
<span class="nx">dest</span> <span class="o">:=</span> <span class="s">"result.pdf"</span>
|
||||
<span class="nx">c</span><span class="p">.</span><span class="nx">Store</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">dest</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
@@ -423,7 +448,20 @@ Also, you have to set both <code>paperWidth</code> and <code>paperHeight</code>.
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>PHP</h3>
|
||||
|
||||
<p>TODO</p>
|
||||
<pre class="chroma"><span class="x">use TheCodingMachine\Gotenberg\Client;
|
||||
</span><span class="x">use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
</span><span class="x">use TheCodingMachine\Gotenberg\HTMLRequest;
|
||||
</span><span class="x">use TheCodingMachine\Gotenberg\Request;
|
||||
</span><span class="x">
|
||||
</span><span class="x">$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
</span><span class="x">$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
</span><span class="x">$request = new HTMLRequest($index);
|
||||
</span><span class="x">$request->setPaperSize(Request::A4);
|
||||
</span><span class="x">$request->setMargins(Request::NO_MARGINS);
|
||||
</span><span class="x">$request->setLandscape(true);
|
||||
</span><span class="x">$dirPath = "/foo";
|
||||
</span><span class="x">$filename = $client->store($request, $dirPath);
|
||||
</span><span class="x"></span></pre>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -442,7 +480,7 @@ Also, you have to set both <code>paperWidth</code> and <code>paperHeight</code>.
|
||||
<p>Markdown conversions work the same as HTML conversions.</p>
|
||||
|
||||
<p>Only difference is that you have access to the Go template function <code>toHTML</code>
|
||||
in the file <code>index.html</code> which will convert a given markdown file to HTML.</p>
|
||||
in the file <code>index.html</code>. This function will convert a given markdown file to HTML.</p>
|
||||
|
||||
<p>For instance:</p>
|
||||
|
||||
@@ -458,16 +496,16 @@ in the file <code>index.html</code> which will convert a given markdown file to
|
||||
<span class="p"><</span><span class="p">/</span><span class="nt">html</span><span class="p">></span>
|
||||
</pre>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="markdown.basic.guzzle" href="#markdown.basic.guzzle">
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="markdown.basic.c_url" href="#markdown.basic.c_url">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Guzzle</h3>
|
||||
</a>cURL</h3>
|
||||
|
||||
<pre class="chroma">$ curl --request POST <span class="se">\
|
||||
</span><span class="se"></span> --url http://localhost:3000/convert/markdown <span class="se">\
|
||||
</span><span class="se"></span> --header <span class="s1">'Content-Type: multipart/form-data'</span> <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@index.html
|
||||
--form <span class="nv">files</span><span class="o">=</span>@file.md
|
||||
> result.pdf
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@index.html <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@file.md <span class="se">\
|
||||
</span><span class="se"></span> > result.pdf
|
||||
</pre>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="markdown.basic.go" href="#markdown.basic.go">
|
||||
@@ -478,12 +516,7 @@ in the file <code>index.html</code> which will convert a given markdown file to
|
||||
|
||||
<span class="kd">func</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="nx">c</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">Client</span><span class="p">{</span><span class="nx">Hostname</span><span class="p">:</span> <span class="s">"http://localhost:3000"</span><span class="p">}</span>
|
||||
<span class="nx">req</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">MarkdownRequest</span><span class="p">{</span>
|
||||
<span class="nx">IndexFilePath</span><span class="p">:</span> <span class="s">"index.html"</span><span class="p">,</span>
|
||||
<span class="nx">MarkdownFilePaths</span><span class="p">:</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span>
|
||||
<span class="s">"file.md"</span><span class="p">,</span>
|
||||
<span class="p">},</span>
|
||||
<span class="p">}</span>
|
||||
<span class="nx">req</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">gotenberg</span><span class="p">.</span><span class="nx">NewMarkdownRequest</span><span class="p">(</span><span class="s">"index.html"</span><span class="p">,</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">"file.md"</span><span class="p">})</span>
|
||||
<span class="nx">dest</span> <span class="o">:=</span> <span class="s">"result.pdf"</span>
|
||||
<span class="nx">c</span><span class="p">.</span><span class="nx">Store</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">dest</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
@@ -493,7 +526,19 @@ in the file <code>index.html</code> which will convert a given markdown file to
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>PHP</h3>
|
||||
|
||||
<p>TODO</p>
|
||||
<pre class="chroma"><span class="x">use TheCodingMachine\Gotenberg\Client;
|
||||
</span><span class="x">use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
</span><span class="x">use TheCodingMachine\Gotenberg\MarkdownRequest;
|
||||
</span><span class="x">
|
||||
</span><span class="x">$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
</span><span class="x">$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
</span><span class="x">$markdowns = [
|
||||
</span><span class="x"> DocumentFactory::makeFromPath('file.md', 'file.md'),
|
||||
</span><span class="x">];
|
||||
</span><span class="x">$request = new MarkdownRequest($index, $markdowns);
|
||||
</span><span class="x">$dirPath = "/foo";
|
||||
</span><span class="x">$filename = $client->store($request, $dirPath);
|
||||
</span><span class="x"></span></pre>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -501,7 +546,7 @@ in the file <code>index.html</code> which will convert a given markdown file to
|
||||
<h1 class="Heading"><a class="Anchor" aria-hidden="true" id="office" href="#office">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Office</h1>
|
||||
<p>Gotenberg provides the endpoint <code>/convert/office</code> for Office documents conversions.</p>
|
||||
<p>Gotenberg provides the endpoint <code>/convert/office</code> for Office document conversions.</p>
|
||||
|
||||
<p>It accepts <code>POST</code> requests with a <code>multipart/form-data</code> Content-Type.</p>
|
||||
|
||||
@@ -512,6 +557,8 @@ in the file <code>index.html</code> which will convert a given markdown file to
|
||||
<p>You may send one or more Office documents. Following file extensions are accepted:</p>
|
||||
|
||||
<ul>
|
||||
<li><code>.txt</code></li>
|
||||
<li><code>.rtf</code></li>
|
||||
<li><code>.doc</code></li>
|
||||
<li><code>.docx</code></li>
|
||||
<li><code>.odt</code></li>
|
||||
@@ -531,16 +578,16 @@ That’s why for Office conversions, the API does only one conversion at a time.
|
||||
See the <a href="#scalability">scalability section</a> to find how to mitigate this issue.</p>
|
||||
</blockquote>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="office.basic.guzzle" href="#office.basic.guzzle">
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="office.basic.c_url" href="#office.basic.c_url">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Guzzle</h3>
|
||||
</a>cURL</h3>
|
||||
|
||||
<pre class="chroma">$ curl --request POST <span class="se">\
|
||||
</span><span class="se"></span> --url http://localhost:3000/convert/office <span class="se">\
|
||||
</span><span class="se"></span> --header <span class="s1">'Content-Type: multipart/form-data'</span> <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@document.docx
|
||||
--form <span class="nv">files</span><span class="o">=</span>@document2.docx
|
||||
> result.pdf
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@document.docx <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@document2.docx <span class="se">\
|
||||
</span><span class="se"></span> > result.pdf
|
||||
</pre>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="office.basic.go" href="#office.basic.go">
|
||||
@@ -551,12 +598,7 @@ See the <a href="#scalability">scalability section</a> to find how to mitigate t
|
||||
|
||||
<span class="kd">func</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="nx">c</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">Client</span><span class="p">{</span><span class="nx">Hostname</span><span class="p">:</span> <span class="s">"http://localhost:3000"</span><span class="p">}</span>
|
||||
<span class="nx">req</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">OfficeRequest</span><span class="p">{</span>
|
||||
<span class="nx">FilePaths</span><span class="p">:</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span>
|
||||
<span class="s">"document.docx"</span><span class="p">,</span>
|
||||
<span class="s">"document2.docx"</span><span class="p">,</span>
|
||||
<span class="p">},</span>
|
||||
<span class="p">}</span>
|
||||
<span class="nx">req</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">gotenberg</span><span class="p">.</span><span class="nx">NewOfficeRequest</span><span class="p">([]</span><span class="kt">string</span><span class="p">{</span><span class="s">"document.docx"</span><span class="p">,</span> <span class="s">"document2.docx"</span><span class="p">})</span>
|
||||
<span class="nx">dest</span> <span class="o">:=</span> <span class="s">"result.pdf"</span>
|
||||
<span class="nx">c</span><span class="p">.</span><span class="nx">Store</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">dest</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
@@ -566,7 +608,81 @@ See the <a href="#scalability">scalability section</a> to find how to mitigate t
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>PHP</h3>
|
||||
|
||||
<p>TODO</p>
|
||||
<pre class="chroma"><span class="x">use TheCodingMachine\Gotenberg\Client;
|
||||
</span><span class="x">use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
</span><span class="x">use TheCodingMachine\Gotenberg\OfficeRequest;
|
||||
</span><span class="x">
|
||||
</span><span class="x">$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
</span><span class="x">$files = [
|
||||
</span><span class="x"> DocumentFactory::makeFromPath('document.docx', 'document.docx'),
|
||||
</span><span class="x"> DocumentFactory::makeFromPath('document2.docx', 'document2.docx'),
|
||||
</span><span class="x">];
|
||||
</span><span class="x">$request = new OfficeRequest($files);
|
||||
</span><span class="x">$dirPath = "/foo";
|
||||
</span><span class="x">$filename = $client->store($request, $dirPath);
|
||||
</span><span class="x"></span></pre>
|
||||
|
||||
<h2 class="Heading"><a class="Anchor" aria-hidden="true" id="office.paper_size_and_orientation" href="#office.paper_size_and_orientation">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Paper size and orientation</h2>
|
||||
|
||||
<p>You may also customize the resulting PDF format.</p>
|
||||
|
||||
<p>By default, it will be rendered with <code>A4</code> size and <code>portrait</code> orientation.</p>
|
||||
|
||||
<blockquote>
|
||||
<p>Paper size has to be provided in <code>inches</code>.
|
||||
Also, you have to set both <code>paperWidth</code> and <code>paperHeight</code>.</p>
|
||||
</blockquote>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="office.paper_size_and_orientation.c_url" href="#office.paper_size_and_orientation.c_url">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>cURL</h3>
|
||||
|
||||
<pre class="chroma">$ curl --request POST <span class="se">\
|
||||
</span><span class="se"></span> --url http://localhost:3000/convert/office <span class="se">\
|
||||
</span><span class="se"></span> --header <span class="s1">'Content-Type: multipart/form-data'</span> <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@document.docx <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">paperWidth</span><span class="o">=</span><span class="m">8</span>.27 <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">paperHeight</span><span class="o">=</span><span class="m">11</span>.27 <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">landscape</span><span class="o">=</span><span class="nb">true</span> <span class="se">\
|
||||
</span><span class="se"></span> > result.pdf
|
||||
</pre>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="office.paper_size_and_orientation.go" href="#office.paper_size_and_orientation.go">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Go</h3>
|
||||
|
||||
<pre class="chroma"><span class="kn">import</span> <span class="s">"github.com/thecodingmachine/gotenberg/pkg"</span>
|
||||
|
||||
<span class="kd">func</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="nx">c</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">Client</span><span class="p">{</span><span class="nx">Hostname</span><span class="p">:</span> <span class="s">"http://localhost:3000"</span><span class="p">}</span>
|
||||
<span class="nx">req</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">gotenberg</span><span class="p">.</span><span class="nx">NewOfficeRequest</span><span class="p">([]</span><span class="kt">string</span><span class="p">{</span><span class="s">"document.docx"</span><span class="p">})</span>
|
||||
<span class="nx">req</span><span class="p">.</span><span class="nx">SetPaperSize</span><span class="p">(</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">A4</span><span class="p">)</span>
|
||||
<span class="nx">req</span><span class="p">.</span><span class="nx">SetLandscape</span><span class="p">(</span><span class="kc">true</span><span class="p">)</span>
|
||||
<span class="nx">dest</span> <span class="o">:=</span> <span class="s">"result.pdf"</span>
|
||||
<span class="nx">c</span><span class="p">.</span><span class="nx">Store</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">dest</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
</pre>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="office.paper_size_and_orientation.php" href="#office.paper_size_and_orientation.php">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>PHP</h3>
|
||||
|
||||
<pre class="chroma"><span class="x">use TheCodingMachine\Gotenberg\Client;
|
||||
</span><span class="x">use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
</span><span class="x">use TheCodingMachine\Gotenberg\OfficeRequest;
|
||||
</span><span class="x">
|
||||
</span><span class="x">$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
</span><span class="x">$files = [
|
||||
</span><span class="x"> DocumentFactory::makeFromPath('document.docx', 'document.docx'),
|
||||
</span><span class="x">];
|
||||
</span><span class="x">$request = new OfficeRequest($files);
|
||||
</span><span class="x">$request->setPaperSize(Request::A4);
|
||||
</span><span class="x">$request->setLandscape(true);
|
||||
</span><span class="x">$dirPath = "/foo";
|
||||
</span><span class="x">$filename = $client->store($request, $dirPath);
|
||||
</span><span class="x"></span></pre>
|
||||
|
||||
<h2 class="Heading"><a class="Anchor" aria-hidden="true" id="office.fonts" href="#office.fonts">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
@@ -598,16 +714,16 @@ See the <a href="#scalability">scalability section</a> to find how to mitigate t
|
||||
<p>Nothing special here: you may send one or more PDF files and the API
|
||||
will merge them and return the resulting PDF file.</p>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="merge.basic.guzzle" href="#merge.basic.guzzle">
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="merge.basic.c_url" href="#merge.basic.c_url">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Guzzle</h3>
|
||||
</a>cURL</h3>
|
||||
|
||||
<pre class="chroma">$ curl --request POST <span class="se">\
|
||||
</span><span class="se"></span> --url http://localhost:3000/merge <span class="se">\
|
||||
</span><span class="se"></span> --header <span class="s1">'Content-Type: multipart/form-data'</span> <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@file.pdf
|
||||
--form <span class="nv">files</span><span class="o">=</span>@file2.pdf
|
||||
> result.pdf
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@file.pdf <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@file2.pdf <span class="se">\
|
||||
</span><span class="se"></span> > result.pdf
|
||||
</pre>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="merge.basic.go" href="#merge.basic.go">
|
||||
@@ -618,12 +734,7 @@ will merge them and return the resulting PDF file.</p>
|
||||
|
||||
<span class="kd">func</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="nx">c</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">Client</span><span class="p">{</span><span class="nx">Hostname</span><span class="p">:</span> <span class="s">"http://localhost:3000"</span><span class="p">}</span>
|
||||
<span class="nx">req</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">MergeRequest</span><span class="p">{</span>
|
||||
<span class="nx">FilePaths</span><span class="p">:</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span>
|
||||
<span class="s">"file.pdf"</span><span class="p">,</span>
|
||||
<span class="s">"file2.pdf"</span><span class="p">,</span>
|
||||
<span class="p">},</span>
|
||||
<span class="p">}</span>
|
||||
<span class="nx">req</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">gotenberg</span><span class="p">.</span><span class="nx">NewMergeRequest</span><span class="p">([]</span><span class="kt">string</span><span class="p">{</span><span class="s">"file.pdf"</span><span class="p">,</span> <span class="s">"file2.pdf"</span><span class="p">})</span>
|
||||
<span class="nx">dest</span> <span class="o">:=</span> <span class="s">"result.pdf"</span>
|
||||
<span class="nx">c</span><span class="p">.</span><span class="nx">Store</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">dest</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
@@ -633,7 +744,19 @@ will merge them and return the resulting PDF file.</p>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>PHP</h3>
|
||||
|
||||
<p>TODO</p>
|
||||
<pre class="chroma"><span class="x">use TheCodingMachine\Gotenberg\Client;
|
||||
</span><span class="x">use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
</span><span class="x">use TheCodingMachine\Gotenberg\MergeRequest;
|
||||
</span><span class="x">
|
||||
</span><span class="x">$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
</span><span class="x">$files = [
|
||||
</span><span class="x"> DocumentFactory::makeFromPath('file.pdf', 'file.pdf'),
|
||||
</span><span class="x"> DocumentFactory::makeFromPath('file2.pdf', 'file2.pdf'),
|
||||
</span><span class="x">];
|
||||
</span><span class="x">$request = new MergeRequest($files);
|
||||
</span><span class="x">$dirPath = "/foo";
|
||||
</span><span class="x">$filename = $client->store($request, $dirPath);
|
||||
</span><span class="x"></span></pre>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -646,22 +769,21 @@ will merge them and return the resulting PDF file.</p>
|
||||
<p>If provided, the API will send the resulting PDF file in a <code>POST</code> request with the <code>application/pdf</code> Content-Type
|
||||
to given URL.</p>
|
||||
|
||||
<p>By doing so, your requests to the API will be done before the conversions are actually done!</p>
|
||||
<p>By doing so, your requests to the API will be over before the conversions are actually done!</p>
|
||||
|
||||
<h2 class="Heading"><a class="Anchor" aria-hidden="true" id="webhook.examples" href="#webhook.examples">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Examples</h2>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="webhook.examples.guzzle" href="#webhook.examples.guzzle">
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="webhook.examples.c_url" href="#webhook.examples.c_url">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>Guzzle</h3>
|
||||
</a>cURL</h3>
|
||||
|
||||
<pre class="chroma">$ curl --request POST <span class="se">\
|
||||
</span><span class="se"></span> --url http://localhost:3000/convert/html <span class="se">\
|
||||
</span><span class="se"></span> --header <span class="s1">'Content-Type: multipart/form-data'</span> <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@index.html
|
||||
--form <span class="nv">webhookURL</span><span class="o">=</span><span class="s1">'http://myapp.com/webhook/'</span>
|
||||
> result.pdf
|
||||
</span><span class="se"></span> --form <span class="nv">files</span><span class="o">=</span>@index.html <span class="se">\
|
||||
</span><span class="se"></span> --form <span class="nv">webhookURL</span><span class="o">=</span><span class="s1">'http://myapp.com/webhook/'</span>
|
||||
</pre>
|
||||
|
||||
<h3 class="Heading"><a class="Anchor" aria-hidden="true" id="webhook.examples.go" href="#webhook.examples.go">
|
||||
@@ -672,14 +794,10 @@ to given URL.</p>
|
||||
|
||||
<span class="kd">func</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</span>
|
||||
<span class="nx">c</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">Client</span><span class="p">{</span><span class="nx">Hostname</span><span class="p">:</span> <span class="s">"http://localhost:3000"</span><span class="p">}</span>
|
||||
<span class="nx">req</span> <span class="o">:=</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">HTMLRequest</span><span class="p">{</span>
|
||||
<span class="nx">IndexFilePath</span><span class="p">:</span> <span class="s">"index.html"</span><span class="p">,</span>
|
||||
<span class="nx">Options</span><span class="p">:</span> <span class="o">&</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">HTMLOptions</span><span class="p">{</span>
|
||||
<span class="nx">WebHookURL</span><span class="p">:</span> <span class="s">"http://myapp.com/webhook/"</span><span class="p">,</span>
|
||||
<span class="p">},</span>
|
||||
<span class="p">}</span>
|
||||
<span class="nx">req</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">gotenberg</span><span class="p">.</span><span class="nx">NewHTMLRequest</span><span class="p">(</span><span class="s">"index.html"</span><span class="p">)</span>
|
||||
<span class="nx">req</span><span class="p">.</span><span class="nx">SetWebhookURL</span><span class="p">(</span><span class="s">"http://myapp.com/webhook/"</span><span class="p">)</span>
|
||||
<span class="nx">dest</span> <span class="o">:=</span> <span class="s">"result.pdf"</span>
|
||||
<span class="nx">resp</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">c</span><span class="p">.</span><span class="nx">Post</span><span class="p">(</span><span class="nx">req</span><span class="p">)</span>
|
||||
<span class="nx">resp</span><span class="p">,</span> <span class="nx">_</span> <span class="o">:=</span> <span class="nx">c</span><span class="p">.</span><span class="nx">Post</span><span class="p">(</span><span class="nx">req</span><span class="p">)</span>
|
||||
<span class="p">}</span>
|
||||
</pre>
|
||||
|
||||
@@ -687,7 +805,16 @@ to given URL.</p>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path></svg>
|
||||
</a>PHP</h3>
|
||||
|
||||
<p>TODO</p>
|
||||
<pre class="chroma"><span class="x">use TheCodingMachine\Gotenberg\Client;
|
||||
</span><span class="x">use TheCodingMachine\Gotenberg\DocumentFactory;
|
||||
</span><span class="x">use TheCodingMachine\Gotenberg\HTMLRequest;
|
||||
</span><span class="x">
|
||||
</span><span class="x">$client = new Client('http://localhost:3000', new \Http\Adapter\Guzzle6\Client());
|
||||
</span><span class="x">$index = DocumentFactory::makeFromPath('index.html', 'index.html');
|
||||
</span><span class="x">$request = new HTMLRequest($index);
|
||||
</span><span class="x">$request->setWebhookURL('http://myapp.com/webhook/');
|
||||
</span><span class="x">$resp = $client->post($request);
|
||||
</span><span class="x"></span></pre>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
2
go.mod
2
go.mod
@@ -4,7 +4,7 @@ require (
|
||||
github.com/derekparker/delve v1.1.0
|
||||
github.com/google/go-cmp v0.2.0 // indirect
|
||||
github.com/gorilla/websocket v1.4.0 // indirect
|
||||
github.com/hhrutter/pdfcpu v0.1.18
|
||||
github.com/hhrutter/pdfcpu v0.1.19
|
||||
github.com/labstack/echo v0.0.0-20181123063703-c7eb8da9ec73
|
||||
github.com/labstack/gommon v0.2.8
|
||||
github.com/mafredri/cdp v0.20.0
|
||||
|
||||
2
go.sum
2
go.sum
@@ -10,6 +10,8 @@ github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/hhrutter/pdfcpu v0.1.18 h1:GX3d6tZxmQlmB5X9VUyOtx7+HZZpR+8ISLqBineP6dc=
|
||||
github.com/hhrutter/pdfcpu v0.1.18/go.mod h1:iaCmXGnOXPIvoGLELZZc4m/GpIopVsvLQ00thrbu8LU=
|
||||
github.com/hhrutter/pdfcpu v0.1.19 h1:J6GjNFDPjurQWallPW9gmz3CcNqBfvgB7Dad9T3e8Hc=
|
||||
github.com/hhrutter/pdfcpu v0.1.19/go.mod h1:iaCmXGnOXPIvoGLELZZc4m/GpIopVsvLQ00thrbu8LU=
|
||||
github.com/labstack/echo v0.0.0-20181123063703-c7eb8da9ec73 h1:oQvA3Xy8274W5Ldgo6Nogy4lX8XO5AaIBsjF5Ggk0IU=
|
||||
github.com/labstack/echo v0.0.0-20181123063703-c7eb8da9ec73/go.mod h1:rS0D1UPvC8/3sXjhSwEq+K1olh7ipbDhjDWATN2KSgA=
|
||||
github.com/labstack/echo v3.3.5+incompatible h1:9PfxPUmasKzeJor9uQTaXLT6WUG/r+vSTmvXxvv3JO4=
|
||||
|
||||
@@ -87,14 +87,15 @@ func newContext(r *resource) (context.Context, context.CancelFunc) {
|
||||
func print(c echo.Context, p printer.Printer, r *resource) error {
|
||||
baseFilename, err := rand.Get()
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting result file name: %v", err)
|
||||
return hijackErr(fmt.Errorf("getting result file name: %v", err), r)
|
||||
}
|
||||
filename := fmt.Sprintf("%s.pdf", baseFilename)
|
||||
fpath := fmt.Sprintf("%s/%s", r.dirPath, filename)
|
||||
if r.webhookURL() == "" {
|
||||
defer r.removeAll()
|
||||
// if no webhook URL given, run conversion
|
||||
// and directly return the resulting PDF file
|
||||
// or and error.
|
||||
// or an error.
|
||||
if err := p.Print(fpath); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -104,6 +105,7 @@ func print(c echo.Context, p printer.Printer, r *resource) error {
|
||||
// run the following lines in a goroutine so that
|
||||
// it doesn't block.
|
||||
go func() {
|
||||
defer r.removeAll()
|
||||
if err := p.Print(fpath); err != nil {
|
||||
c.Logger().Errorf("%v", err)
|
||||
return
|
||||
@@ -123,3 +125,10 @@ func print(c echo.Context, p printer.Printer, r *resource) error {
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
func hijackErr(err error, r *resource) error {
|
||||
if r != nil {
|
||||
defer r.removeAll()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -8,9 +8,8 @@ import (
|
||||
func convertHTML(c echo.Context) error {
|
||||
r, err := newResource(c)
|
||||
if err != nil {
|
||||
return err
|
||||
return hijackErr(err, r)
|
||||
}
|
||||
defer r.removeAll()
|
||||
ctx, cancel := newContext(r)
|
||||
if cancel != nil {
|
||||
defer cancel()
|
||||
@@ -18,26 +17,26 @@ func convertHTML(c echo.Context) error {
|
||||
p := &printer.HTML{Context: ctx}
|
||||
indexPath, err := r.filePath("index.html")
|
||||
if err != nil {
|
||||
return err
|
||||
return hijackErr(err, r)
|
||||
}
|
||||
p.WithLocalURL(indexPath)
|
||||
headerPath, _ := r.filePath("header.html")
|
||||
if err := p.WithHeaderFile(headerPath); err != nil {
|
||||
return err
|
||||
return hijackErr(err, r)
|
||||
}
|
||||
footerPath, _ := r.filePath("footer.html")
|
||||
if err := p.WithFooterFile(footerPath); err != nil {
|
||||
return err
|
||||
return hijackErr(err, r)
|
||||
}
|
||||
paperSize, err := r.paperSize()
|
||||
if err != nil {
|
||||
return err
|
||||
return hijackErr(err, r)
|
||||
}
|
||||
p.PaperWidth = paperSize[0]
|
||||
p.PaperHeight = paperSize[1]
|
||||
paperMargins, err := r.paperMargins()
|
||||
if err != nil {
|
||||
return err
|
||||
return hijackErr(err, r)
|
||||
}
|
||||
p.MarginTop = paperMargins[0]
|
||||
p.MarginBottom = paperMargins[1]
|
||||
@@ -45,7 +44,7 @@ func convertHTML(c echo.Context) error {
|
||||
p.MarginRight = paperMargins[3]
|
||||
landscape, err := r.landscape()
|
||||
if err != nil {
|
||||
return err
|
||||
return hijackErr(err, r)
|
||||
}
|
||||
p.Landscape = landscape
|
||||
return print(c, p, r)
|
||||
|
||||
@@ -11,11 +11,14 @@ import (
|
||||
)
|
||||
|
||||
func TestHTML(t *testing.T) {
|
||||
body, contentType := test.HTMLMultipartForm(t)
|
||||
body, contentType := test.HTMLTestMultipartForm(t)
|
||||
req := httptest.NewRequest(http.MethodPost, "/convert/html", body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
rec := httptest.NewRecorder()
|
||||
e := echo.New()
|
||||
c := e.NewContext(req, rec)
|
||||
assert.NoError(t, convertHTML(c))
|
||||
if assert.NoError(t, convertHTML(c)) {
|
||||
assert.Equal(t, http.StatusOK, rec.Code)
|
||||
assert.Equal(t, "application/pdf", rec.Header().Get(echo.HeaderContentType))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,35 +8,34 @@ import (
|
||||
func convertMarkdown(c echo.Context) error {
|
||||
r, err := newResource(c)
|
||||
if err != nil {
|
||||
return err
|
||||
return hijackErr(err, r)
|
||||
}
|
||||
defer r.removeAll()
|
||||
ctx, cancel := newContext(r)
|
||||
if cancel != nil {
|
||||
defer cancel()
|
||||
}
|
||||
indexPath, err := r.filePath("index.html")
|
||||
if err != nil {
|
||||
return err
|
||||
return hijackErr(err, r)
|
||||
}
|
||||
p := &printer.Markdown{Context: ctx, TemplatePath: indexPath}
|
||||
headerPath, _ := r.filePath("header.html")
|
||||
if err := p.WithHeaderFile(headerPath); err != nil {
|
||||
return err
|
||||
return hijackErr(err, r)
|
||||
}
|
||||
footerPath, _ := r.filePath("footer.html")
|
||||
if err := p.WithFooterFile(footerPath); err != nil {
|
||||
return err
|
||||
return hijackErr(err, r)
|
||||
}
|
||||
paperSize, err := r.paperSize()
|
||||
if err != nil {
|
||||
return err
|
||||
return hijackErr(err, r)
|
||||
}
|
||||
p.PaperWidth = paperSize[0]
|
||||
p.PaperHeight = paperSize[1]
|
||||
paperMargins, err := r.paperMargins()
|
||||
if err != nil {
|
||||
return err
|
||||
return hijackErr(err, r)
|
||||
}
|
||||
p.MarginTop = paperMargins[0]
|
||||
p.MarginBottom = paperMargins[1]
|
||||
@@ -44,7 +43,7 @@ func convertMarkdown(c echo.Context) error {
|
||||
p.MarginRight = paperMargins[3]
|
||||
landscape, err := r.landscape()
|
||||
if err != nil {
|
||||
return err
|
||||
return hijackErr(err, r)
|
||||
}
|
||||
p.Landscape = landscape
|
||||
return print(c, p, r)
|
||||
|
||||
@@ -11,11 +11,14 @@ import (
|
||||
)
|
||||
|
||||
func TestMarkdown(t *testing.T) {
|
||||
body, contentType := test.MarkdownMultipartForm(t)
|
||||
body, contentType := test.MarkdownTestMultipartForm(t)
|
||||
req := httptest.NewRequest(http.MethodPost, "/convert/markdown", body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
rec := httptest.NewRecorder()
|
||||
e := echo.New()
|
||||
c := e.NewContext(req, rec)
|
||||
assert.NoError(t, convertMarkdown(c))
|
||||
if assert.NoError(t, convertMarkdown(c)) {
|
||||
assert.Equal(t, http.StatusOK, rec.Code)
|
||||
assert.Equal(t, "application/pdf", rec.Header().Get(echo.HeaderContentType))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -13,23 +14,26 @@ import (
|
||||
func merge(c echo.Context) error {
|
||||
r, err := newResource(c)
|
||||
if err != nil {
|
||||
return err
|
||||
return hijackErr(err, r)
|
||||
}
|
||||
defer r.removeAll()
|
||||
fpaths, err := r.filePaths([]string{".pdf"})
|
||||
if err != nil {
|
||||
return err
|
||||
return hijackErr(err, r)
|
||||
}
|
||||
if len(fpaths) == 0 {
|
||||
return hijackErr(errors.New("no suitable PDF files to merge"), r)
|
||||
}
|
||||
baseFilename, err := rand.Get()
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting result file name: %v", err)
|
||||
return hijackErr(fmt.Errorf("getting result file name: %v", err), r)
|
||||
}
|
||||
filename := fmt.Sprintf("%s.pdf", baseFilename)
|
||||
fpath := fmt.Sprintf("%s/%s", r.dirPath, filename)
|
||||
if r.webhookURL() == "" {
|
||||
defer r.removeAll()
|
||||
// if no webhook URL given, run merge
|
||||
// and directly return the resulting PDF file
|
||||
// or and error.
|
||||
// or an error.
|
||||
if err := printer.Merge(fpaths, fpath); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -39,6 +43,7 @@ func merge(c echo.Context) error {
|
||||
// run the following lines in a goroutine so that
|
||||
// it doesn't block.
|
||||
go func() {
|
||||
defer r.removeAll()
|
||||
if err := printer.Merge(fpaths, fpath); err != nil {
|
||||
c.Logger().Errorf("%v", err)
|
||||
return
|
||||
|
||||
@@ -11,11 +11,14 @@ import (
|
||||
)
|
||||
|
||||
func TestMerge(t *testing.T) {
|
||||
body, contentType := test.PDFMultipartForm(t)
|
||||
body, contentType := test.PDFTestMultipartForm(t)
|
||||
req := httptest.NewRequest(http.MethodPost, "/merge", body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
rec := httptest.NewRecorder()
|
||||
e := echo.New()
|
||||
c := e.NewContext(req, rec)
|
||||
assert.NoError(t, merge(c))
|
||||
if assert.NoError(t, merge(c)) {
|
||||
assert.Equal(t, http.StatusOK, rec.Code)
|
||||
assert.Equal(t, "application/pdf", rec.Header().Get(echo.HeaderContentType))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
)
|
||||
|
||||
var officeExts = []string{
|
||||
".txt",
|
||||
".rtf",
|
||||
".doc",
|
||||
".docx",
|
||||
".odt",
|
||||
@@ -22,20 +24,30 @@ var officeExts = []string{
|
||||
func convertOffice(c echo.Context) error {
|
||||
r, err := newResource(c)
|
||||
if err != nil {
|
||||
return err
|
||||
return hijackErr(err, r)
|
||||
}
|
||||
defer r.removeAll()
|
||||
ctx, cancel := newContext(r)
|
||||
if cancel != nil {
|
||||
defer cancel()
|
||||
}
|
||||
fpaths, err := r.filePaths(officeExts)
|
||||
if err != nil {
|
||||
return err
|
||||
return hijackErr(err, r)
|
||||
}
|
||||
if len(fpaths) == 0 {
|
||||
return errors.New("no suitable office documents to convert")
|
||||
return hijackErr(errors.New("no suitable office documents to convert"), r)
|
||||
}
|
||||
p := &printer.Office{Context: ctx, FilePaths: fpaths}
|
||||
paperSize, err := r.paperSize()
|
||||
if err != nil {
|
||||
return hijackErr(err, r)
|
||||
}
|
||||
p.PaperWidth = paperSize[0]
|
||||
p.PaperHeight = paperSize[1]
|
||||
landscape, err := r.landscape()
|
||||
if err != nil {
|
||||
return hijackErr(err, r)
|
||||
}
|
||||
p.Landscape = landscape
|
||||
return print(c, p, r)
|
||||
}
|
||||
|
||||
@@ -11,11 +11,14 @@ import (
|
||||
)
|
||||
|
||||
func TestOffice(t *testing.T) {
|
||||
body, contentType := test.OfficeMultipartForm(t)
|
||||
body, contentType := test.OfficeTestMultipartForm(t)
|
||||
req := httptest.NewRequest(http.MethodPost, "/convert/office", body)
|
||||
req.Header.Set(echo.HeaderContentType, contentType)
|
||||
rec := httptest.NewRecorder()
|
||||
e := echo.New()
|
||||
c := e.NewContext(req, rec)
|
||||
assert.NoError(t, convertOffice(c))
|
||||
if assert.NoError(t, convertOffice(c)) {
|
||||
assert.Equal(t, http.StatusOK, rec.Code)
|
||||
assert.Equal(t, "application/pdf", rec.Header().Get(echo.HeaderContentType))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,17 +49,17 @@ func newResource(c echo.Context) (*resource, error) {
|
||||
r := &resource{values: v, dirPath: dirPath}
|
||||
form, err := c.MultipartForm()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getting multipart form: %v", err)
|
||||
return r, fmt.Errorf("getting multipart form: %v", err)
|
||||
}
|
||||
for _, files := range form.File {
|
||||
for _, fh := range files {
|
||||
in, err := fh.Open()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: opening file: %v", fh.Filename, err)
|
||||
return r, fmt.Errorf("%s: opening file: %v", fh.Filename, err)
|
||||
}
|
||||
defer in.Close()
|
||||
if err := r.writeFile(fh.Filename, in); err != nil {
|
||||
return nil, err
|
||||
return r, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,8 +54,9 @@ func (c *Chrome) getFullname() string {
|
||||
|
||||
func (c *Chrome) isViable() bool {
|
||||
// check if Chrome is correctly running.
|
||||
devt := devtool.New("http://127.0.0.1:9222")
|
||||
_, err := devt.Create(context.TODO())
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
_, err := devtool.New("http://localhost:9222").Version(ctx)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,52 +1,7 @@
|
||||
/*
|
||||
Package printer contains structs which convert
|
||||
a specific file type to PDF:
|
||||
a specific file type to PDF.
|
||||
|
||||
// converting HTML to PDF.
|
||||
p := &printer.HTML{
|
||||
Context: context.Background(),
|
||||
PaperWidth: 8.27,
|
||||
PaperHeight: 11.7,
|
||||
Landscape: false,
|
||||
}
|
||||
p.WithLocalURL("index.html")
|
||||
if err := p.Print("result.pdf"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// converting Markdown to PDF:
|
||||
// it assumes here that our template "index.html"
|
||||
// will call toHTML method to convert
|
||||
// markdown files to HTML.
|
||||
p := &printer.Markdown{
|
||||
Context: context.Background(),
|
||||
TemplatePath: "index.html",
|
||||
PaperWidth: 8.27,
|
||||
PaperHeight: 11.7,
|
||||
Landscape: false,
|
||||
}
|
||||
if err := p.Print("result.pdf"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// converting Office documents to PDF:
|
||||
// it converts each files independently and
|
||||
// then merge them.
|
||||
//
|
||||
// Also, as unoconv cannot perform
|
||||
// concurrent conversions, a lock is applied.
|
||||
p := &printer.Office{
|
||||
Context: ctx,
|
||||
FilePaths: []string{"document.docx", "presentation.pptx"}
|
||||
}
|
||||
if err := p.Print("result.pdf"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
It is also able to merge a list of PDF files:
|
||||
|
||||
if err := printer.Merge([]string{"foo.pdf", "bar.pdf"}, "result.pdf"); err != nil {
|
||||
return err
|
||||
}
|
||||
It is also able to merge a list of PDF files.
|
||||
*/
|
||||
package printer
|
||||
|
||||
@@ -36,14 +36,15 @@ const defaultHeaderFooterHTML string = "<html><head></head><body></body></html>"
|
||||
// Print converts HTML to PDF.
|
||||
// Credits: https://medium.com/compass-true-north/go-service-to-convert-web-pages-to-pdf-using-headless-chrome-5fd9ffbae1af
|
||||
func (html *HTML) Print(destination string) error {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
// use the DevTools HTTP/JSON API to manage targets (e.g. pages, webworkers).
|
||||
devt := devtool.New("http://127.0.0.1:9222")
|
||||
pt, err := devt.Create(html.Context)
|
||||
devt, err := devtool.New("http://localhost:9222").Version(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating DevTools target: %v", err)
|
||||
}
|
||||
// open a new RPC connection to the Chrome Debugging Protocol target.
|
||||
conn, err := rpcc.DialContext(html.Context, pt.WebSocketDebuggerURL)
|
||||
conn, err := rpcc.DialContext(html.Context, devt.WebSocketDebuggerURL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating RPC connection: %v", err)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/thecodingmachine/gotenberg/internal/pkg/rand"
|
||||
@@ -16,8 +17,11 @@ var mu sync.Mutex
|
||||
|
||||
// Office facilitates Office documents to PDF conversion.
|
||||
type Office struct {
|
||||
Context context.Context
|
||||
FilePaths []string
|
||||
Context context.Context
|
||||
FilePaths []string
|
||||
PaperWidth float64
|
||||
PaperHeight float64
|
||||
Landscape bool
|
||||
}
|
||||
|
||||
// Print converts Office documents to PDF.
|
||||
@@ -32,14 +36,24 @@ func (o *Office) Print(destination string) error {
|
||||
return err
|
||||
}
|
||||
tmpDest := fmt.Sprintf("%s/%s.pdf", dirPath, baseFilename)
|
||||
paperSize, err := unoconvPaperSize(o.PaperWidth, o.PaperHeight)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmdArgs := []string{
|
||||
"--format",
|
||||
"pdf",
|
||||
"--printer",
|
||||
paperSize,
|
||||
}
|
||||
if o.Landscape {
|
||||
cmdArgs = append(cmdArgs, "--printer", "PaperOrientation=landscape")
|
||||
}
|
||||
cmdArgs = append(cmdArgs, "--output", tmpDest, fpath)
|
||||
cmd := exec.CommandContext(
|
||||
o.Context,
|
||||
"unoconv",
|
||||
"--format",
|
||||
"pdf",
|
||||
"--output",
|
||||
tmpDest,
|
||||
fpath,
|
||||
cmdArgs...,
|
||||
)
|
||||
_, err = cmd.Output()
|
||||
if o.Context.Err() == context.DeadlineExceeded {
|
||||
@@ -56,6 +70,18 @@ func (o *Office) Print(destination string) error {
|
||||
return Merge(fpaths, destination)
|
||||
}
|
||||
|
||||
func unoconvPaperSize(paperWidth, paperHeight float64) (string, error) {
|
||||
width, err := strconv.Atoi(fmt.Sprintf("%.0f", paperWidth*25.4))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("%0.f: converting width to millimiter: %v", paperWidth, err)
|
||||
}
|
||||
height, err := strconv.Atoi(fmt.Sprintf("%.0f", paperHeight*25.4))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("%0.f: converting height to millimiter: %v", paperHeight, err)
|
||||
}
|
||||
return fmt.Sprintf("PaperSize=%dx%d", width, height), nil
|
||||
}
|
||||
|
||||
// Compile-time checks to ensure type implements desired interfaces.
|
||||
var (
|
||||
_ = Printer(new(Office))
|
||||
|
||||
@@ -20,6 +20,8 @@ func TestOffice(t *testing.T) {
|
||||
Context: ctx,
|
||||
FilePaths: []string{
|
||||
fmt.Sprintf("%s/%s", dirPath, "document.docx"),
|
||||
fmt.Sprintf("%s/%s", dirPath, "document.txt"),
|
||||
fmt.Sprintf("%s/%s", dirPath, "document.rtf"),
|
||||
},
|
||||
}
|
||||
dst := fmt.Sprintf("%s/%s", dirPath, "foo.pdf")
|
||||
|
||||
@@ -5,9 +5,16 @@ import (
|
||||
"io/ioutil"
|
||||
|
||||
pdfcpuAPI "github.com/hhrutter/pdfcpu/pkg/api"
|
||||
pdfcpuLog "github.com/hhrutter/pdfcpu/pkg/log"
|
||||
pdfcpuConfig "github.com/hhrutter/pdfcpu/pkg/pdfcpu"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// disable loggers when merging
|
||||
// PDFs.
|
||||
pdfcpuLog.DisableLoggers()
|
||||
}
|
||||
|
||||
// Printer is a type that can create a PDF file from a source.
|
||||
// The source is defined in the underlying implementation.
|
||||
type Printer interface {
|
||||
|
||||
@@ -16,7 +16,7 @@ func TestMerge(t *testing.T) {
|
||||
err := Merge(
|
||||
[]string{
|
||||
fmt.Sprintf("%s/%s", dirPath, "gotenberg.pdf"),
|
||||
fmt.Sprintf("%s/%s", dirPath, "gotenberg.pdf"),
|
||||
fmt.Sprintf("%s/%s", dirPath, "gotenberg_bis.pdf"),
|
||||
},
|
||||
dst,
|
||||
)
|
||||
|
||||
@@ -16,19 +16,17 @@ import "github.com/thecodingmachine/gotenberg/pkg"
|
||||
func main() {
|
||||
// HTML conversion example.
|
||||
c := &gotenberg.Client{Hostname: "http://localhost:3000"}
|
||||
req := &gotenberg.HTMLRequest{
|
||||
IndexFilePath: "index.html",
|
||||
AssetFilePaths: []string{
|
||||
"style.css",
|
||||
"img.png",
|
||||
},
|
||||
Options: &gotenberg.HTMLOptions{
|
||||
HeaderFilePath: "header.html",
|
||||
FooterFilePath: "footer.html",
|
||||
PaperSize: gotenberg.A4,
|
||||
PaperMargins: gotenberg.NormalMargins,
|
||||
},
|
||||
}
|
||||
req, _ := gotenberg.NewHTMLRequest("index.html")
|
||||
req.SetHeader("header.html")
|
||||
req.SetFooter("footer.html")
|
||||
req.SetAssets([]string{
|
||||
"font.woff",
|
||||
"img.gif",
|
||||
"style.css",
|
||||
})
|
||||
req.SetPaperSize(gotenberg.A4)
|
||||
req.SetMargins(gotenberg.NormalMargins)
|
||||
req.SetLandscape(false)
|
||||
dest := "foo.pdf"
|
||||
c.Store(req, dest)
|
||||
}
|
||||
|
||||
@@ -59,18 +59,35 @@ type Client struct {
|
||||
// form values and form files to
|
||||
// the Gotenberg API.
|
||||
type Request interface {
|
||||
validate() error
|
||||
SetWebhookURL(webhookURL string)
|
||||
getPostURL() string
|
||||
getFormValues() map[string]string
|
||||
getFormFiles() map[string]string
|
||||
}
|
||||
|
||||
// ChromeRequest is a type for sending
|
||||
// conversion requests which will be
|
||||
// handle by Google Chrome.
|
||||
type ChromeRequest interface {
|
||||
SetHeader(fpath string) error
|
||||
SetFooter(fpath string) error
|
||||
SetAssets(fpaths []string) error
|
||||
SetPaperSize(size [2]float64)
|
||||
SetMargins(margins [4]float64)
|
||||
SetLandscape(isLandscape bool)
|
||||
}
|
||||
|
||||
// UnoconvRequest is a type for sending
|
||||
// conversion requests which will be
|
||||
// handle by unoconv.
|
||||
type UnoconvRequest interface {
|
||||
SetPaperSize(size [2]float64)
|
||||
SetLandscape(landscape bool)
|
||||
}
|
||||
|
||||
// Post sends a request to the Gotenberg API
|
||||
// and returns the response.
|
||||
func (c *Client) Post(req Request) (*http.Response, error) {
|
||||
if err := req.validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
body, contentType, err := multipartForm(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
27
pkg/doc.go
27
pkg/doc.go
@@ -2,30 +2,7 @@
|
||||
Package gotenberg is a Go client for
|
||||
interacting with a Gotenberg API.
|
||||
|
||||
For instance, if you want to convert HTML:
|
||||
|
||||
import "github.com/thecodingmachine/gotenberg/pkg"
|
||||
|
||||
func main() {
|
||||
// HTML conversion example.
|
||||
c := &gotenberg.Client{Hostname: "http://localhost:3000"}
|
||||
req := &gotenberg.HTMLRequest{
|
||||
IndexFilePath: "index.html",
|
||||
AssetFilePaths: []string{
|
||||
"style.css",
|
||||
"img.png",
|
||||
},
|
||||
Options: &gotenberg.HTMLOptions{
|
||||
HeaderFilePath: "header.html",
|
||||
FooterFilePath: "footer.html",
|
||||
PaperSize: gotenberg.A4,
|
||||
PaperMargins: gotenberg.NormalMargins,
|
||||
},
|
||||
}
|
||||
dest := "foo.pdf"
|
||||
c.Store(req, dest)
|
||||
}
|
||||
|
||||
For more complete usages, head to the https://thecodingmachine.gotenberg.github.io.
|
||||
For more complete usages, head to the documentation:
|
||||
https://thecodingmachine.gotenberg.github.io.
|
||||
*/
|
||||
package gotenberg
|
||||
|
||||
108
pkg/html.go
108
pkg/html.go
@@ -9,64 +9,89 @@ import (
|
||||
// HTMLRequest facilitates HTML conversion
|
||||
// with the Gotenberg API.
|
||||
type HTMLRequest struct {
|
||||
IndexFilePath string
|
||||
AssetFilePaths []string
|
||||
Options *HTMLOptions
|
||||
indexFilePath string
|
||||
headerFilePath string
|
||||
footerFilePath string
|
||||
assetFilePaths []string
|
||||
values map[string]string
|
||||
}
|
||||
|
||||
// HTMLOptions gathers all options
|
||||
// for HTML conversion with the Gotenberg API.
|
||||
type HTMLOptions struct {
|
||||
WebHookURL string
|
||||
HeaderFilePath string
|
||||
FooterFilePath string
|
||||
PaperSize [2]float64
|
||||
PaperMargins [4]float64
|
||||
Landscape bool
|
||||
// NewHTMLRequest create HTMLRequest.
|
||||
func NewHTMLRequest(indexFilePath string) (*HTMLRequest, error) {
|
||||
if !fileExists(indexFilePath) {
|
||||
return nil, fmt.Errorf("%s: index file does not exist", indexFilePath)
|
||||
}
|
||||
return &HTMLRequest{indexFilePath: indexFilePath, values: make(map[string]string)}, nil
|
||||
}
|
||||
|
||||
func (html *HTMLRequest) validate() error {
|
||||
if !fileExists(html.IndexFilePath) {
|
||||
return fmt.Errorf("%s: index file does not exist", html.IndexFilePath)
|
||||
}
|
||||
if html.Options.HeaderFilePath != "" && !fileExists(html.Options.HeaderFilePath) {
|
||||
return fmt.Errorf("%s: header file does not exist", html.Options.HeaderFilePath)
|
||||
}
|
||||
if html.Options.FooterFilePath != "" && !fileExists(html.Options.FooterFilePath) {
|
||||
return fmt.Errorf("%s: footer file does not exist", html.Options.FooterFilePath)
|
||||
// SetWebhookURL sets webhookURL form field.
|
||||
func (html *HTMLRequest) SetWebhookURL(webhookURL string) {
|
||||
html.values[webhookURL] = webhookURL
|
||||
}
|
||||
|
||||
// SetHeader sets header form file.
|
||||
func (html *HTMLRequest) SetHeader(fpath string) error {
|
||||
if !fileExists(fpath) {
|
||||
return fmt.Errorf("%s: header file does not exist", fpath)
|
||||
}
|
||||
html.headerFilePath = fpath
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetFooter sets footer form file.
|
||||
func (html *HTMLRequest) SetFooter(fpath string) error {
|
||||
if !fileExists(fpath) {
|
||||
return fmt.Errorf("%s: footer file does not exist", fpath)
|
||||
}
|
||||
html.footerFilePath = fpath
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetAssets sets assets form files.
|
||||
func (html *HTMLRequest) SetAssets(fpaths []string) error {
|
||||
for _, fpath := range fpaths {
|
||||
if !fileExists(fpath) {
|
||||
return fmt.Errorf("%s: file does not exist", fpath)
|
||||
}
|
||||
}
|
||||
html.assetFilePaths = fpaths
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetPaperSize sets paperWidth and paperHeight form fields.
|
||||
func (html *HTMLRequest) SetPaperSize(size [2]float64) {
|
||||
html.values[paperWidth] = fmt.Sprintf("%f", size[0])
|
||||
html.values[paperHeight] = fmt.Sprintf("%f", size[1])
|
||||
}
|
||||
|
||||
// SetMargins sets marginTop, marginBottom,
|
||||
// marginLeft and marginRight form fields.
|
||||
func (html *HTMLRequest) SetMargins(margins [4]float64) {
|
||||
html.values[marginTop] = fmt.Sprintf("%f", margins[0])
|
||||
html.values[marginBottom] = fmt.Sprintf("%f", margins[1])
|
||||
html.values[marginLeft] = fmt.Sprintf("%f", margins[2])
|
||||
html.values[marginRight] = fmt.Sprintf("%f", margins[3])
|
||||
}
|
||||
|
||||
// SetLandscape sets landscape form field.
|
||||
func (html *HTMLRequest) SetLandscape(isLandscape bool) {
|
||||
html.values[landscape] = strconv.FormatBool(isLandscape)
|
||||
}
|
||||
|
||||
func (html *HTMLRequest) getPostURL() string {
|
||||
return "/convert/html"
|
||||
}
|
||||
|
||||
func (html *HTMLRequest) getFormValues() map[string]string {
|
||||
if html.Options == nil {
|
||||
html.Options = &HTMLOptions{}
|
||||
}
|
||||
values := make(map[string]string)
|
||||
values[webhookURL] = html.Options.WebHookURL
|
||||
values[paperWidth] = fmt.Sprintf("%f", html.Options.PaperSize[0])
|
||||
values[paperHeight] = fmt.Sprintf("%f", html.Options.PaperSize[1])
|
||||
values[marginTop] = fmt.Sprintf("%f", html.Options.PaperMargins[0])
|
||||
values[marginBottom] = fmt.Sprintf("%f", html.Options.PaperMargins[1])
|
||||
values[marginLeft] = fmt.Sprintf("%f", html.Options.PaperMargins[2])
|
||||
values[marginRight] = fmt.Sprintf("%f", html.Options.PaperMargins[3])
|
||||
values[landscape] = strconv.FormatBool(html.Options.Landscape)
|
||||
return values
|
||||
return html.values
|
||||
}
|
||||
|
||||
func (html *HTMLRequest) getFormFiles() map[string]string {
|
||||
if html.Options == nil {
|
||||
html.Options = &HTMLOptions{}
|
||||
}
|
||||
files := make(map[string]string)
|
||||
files["index.html"] = html.IndexFilePath
|
||||
files["header.html"] = html.Options.HeaderFilePath
|
||||
files["footer.html"] = html.Options.FooterFilePath
|
||||
for _, fpath := range html.AssetFilePaths {
|
||||
files["index.html"] = html.indexFilePath
|
||||
files["header.html"] = html.headerFilePath
|
||||
files["footer.html"] = html.footerFilePath
|
||||
for _, fpath := range html.assetFilePaths {
|
||||
files[filepath.Base(fpath)] = fpath
|
||||
}
|
||||
return files
|
||||
@@ -75,4 +100,5 @@ func (html *HTMLRequest) getFormFiles() map[string]string {
|
||||
// Compile-time checks to ensure type implements desired interfaces.
|
||||
var (
|
||||
_ = Request(new(HTMLRequest))
|
||||
_ = ChromeRequest(new(HTMLRequest))
|
||||
)
|
||||
|
||||
@@ -13,20 +13,21 @@ import (
|
||||
|
||||
func TestHTML(t *testing.T) {
|
||||
c := &Client{Hostname: "http://localhost:3000"}
|
||||
req := &HTMLRequest{
|
||||
IndexFilePath: test.HTMLTestFilePath(t, "index.html"),
|
||||
AssetFilePaths: []string{
|
||||
test.HTMLTestFilePath(t, "font.woff"),
|
||||
test.HTMLTestFilePath(t, "img.gif"),
|
||||
test.HTMLTestFilePath(t, "style.css"),
|
||||
},
|
||||
Options: &HTMLOptions{
|
||||
HeaderFilePath: test.HTMLTestFilePath(t, "header.html"),
|
||||
FooterFilePath: test.HTMLTestFilePath(t, "footer.html"),
|
||||
PaperSize: A4,
|
||||
PaperMargins: NormalMargins,
|
||||
},
|
||||
}
|
||||
req, err := NewHTMLRequest(test.HTMLTestFilePath(t, "index.html"))
|
||||
require.Nil(t, err)
|
||||
err = req.SetHeader(test.HTMLTestFilePath(t, "header.html"))
|
||||
require.Nil(t, err)
|
||||
err = req.SetFooter(test.HTMLTestFilePath(t, "footer.html"))
|
||||
require.Nil(t, err)
|
||||
err = req.SetAssets([]string{
|
||||
test.HTMLTestFilePath(t, "font.woff"),
|
||||
test.HTMLTestFilePath(t, "img.gif"),
|
||||
test.HTMLTestFilePath(t, "style.css"),
|
||||
})
|
||||
require.Nil(t, err)
|
||||
req.SetPaperSize(A4)
|
||||
req.SetMargins(NormalMargins)
|
||||
req.SetLandscape(false)
|
||||
dirPath, err := rand.Get()
|
||||
require.Nil(t, err)
|
||||
dest := fmt.Sprintf("%s/foo.pdf", dirPath)
|
||||
@@ -36,3 +37,11 @@ func TestHTML(t *testing.T) {
|
||||
err = os.RemoveAll(dirPath)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestConcurrentHTML(t *testing.T) {
|
||||
for i := 0; i < 10; i++ {
|
||||
go func() {
|
||||
TestHTML(t)
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
124
pkg/markdown.go
124
pkg/markdown.go
@@ -9,73 +9,102 @@ import (
|
||||
// MarkdownRequest facilitates Markdown conversion
|
||||
// with the Gotenberg API.
|
||||
type MarkdownRequest struct {
|
||||
IndexFilePath string
|
||||
MarkdownFilePaths []string
|
||||
AssetFilePaths []string
|
||||
Options *MarkdownOptions
|
||||
indexFilePath string
|
||||
markdownFilePaths []string
|
||||
headerFilePath string
|
||||
footerFilePath string
|
||||
assetFilePaths []string
|
||||
values map[string]string
|
||||
}
|
||||
|
||||
// MarkdownOptions gathers all options
|
||||
// for Markdown conversion with the Gotenberg API.
|
||||
type MarkdownOptions struct {
|
||||
WebHookURL string
|
||||
HeaderFilePath string
|
||||
FooterFilePath string
|
||||
PaperSize [2]float64
|
||||
PaperMargins [4]float64
|
||||
Landscape bool
|
||||
}
|
||||
|
||||
func (markdown *MarkdownRequest) validate() error {
|
||||
if !fileExists(markdown.IndexFilePath) {
|
||||
return fmt.Errorf("%s: index file does not exist", markdown.IndexFilePath)
|
||||
// NewMarkdownRequest create MarkdownRequest.
|
||||
func NewMarkdownRequest(indexFilePath string, markdownFilePaths []string) (*MarkdownRequest, error) {
|
||||
if !fileExists(indexFilePath) {
|
||||
return nil, fmt.Errorf("%s: index file does not exist", indexFilePath)
|
||||
}
|
||||
if markdown.Options.HeaderFilePath != "" && !fileExists(markdown.Options.HeaderFilePath) {
|
||||
return fmt.Errorf("%s: header file does not exist", markdown.Options.HeaderFilePath)
|
||||
}
|
||||
if markdown.Options.FooterFilePath != "" && !fileExists(markdown.Options.FooterFilePath) {
|
||||
return fmt.Errorf("%s: footer file does not exist", markdown.Options.FooterFilePath)
|
||||
}
|
||||
for _, fpath := range markdown.MarkdownFilePaths {
|
||||
for _, fpath := range markdownFilePaths {
|
||||
if !fileExists(fpath) {
|
||||
return fmt.Errorf("%s: markdown file does not exist", fpath)
|
||||
return nil, fmt.Errorf("%s: markdown file does not exist", fpath)
|
||||
}
|
||||
}
|
||||
return &MarkdownRequest{
|
||||
indexFilePath: indexFilePath,
|
||||
markdownFilePaths: markdownFilePaths,
|
||||
values: make(map[string]string),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SetWebhookURL sets webhookURL form field.
|
||||
func (markdown *MarkdownRequest) SetWebhookURL(webhookURL string) {
|
||||
markdown.values[webhookURL] = webhookURL
|
||||
}
|
||||
|
||||
// SetHeader sets header form file.
|
||||
func (markdown *MarkdownRequest) SetHeader(fpath string) error {
|
||||
if !fileExists(fpath) {
|
||||
return fmt.Errorf("%s: header file does not exist", fpath)
|
||||
}
|
||||
markdown.headerFilePath = fpath
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetFooter sets footer form file.
|
||||
func (markdown *MarkdownRequest) SetFooter(fpath string) error {
|
||||
if !fileExists(fpath) {
|
||||
return fmt.Errorf("%s: footer file does not exist", fpath)
|
||||
}
|
||||
markdown.footerFilePath = fpath
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetAssets sets assets form files.
|
||||
func (markdown *MarkdownRequest) SetAssets(fpaths []string) error {
|
||||
for _, fpath := range fpaths {
|
||||
if !fileExists(fpath) {
|
||||
return fmt.Errorf("%s: file does not exist", fpath)
|
||||
}
|
||||
}
|
||||
markdown.assetFilePaths = fpaths
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetPaperSize sets paperWidth and paperHeight form fields.
|
||||
func (markdown *MarkdownRequest) SetPaperSize(size [2]float64) {
|
||||
markdown.values[paperWidth] = fmt.Sprintf("%f", size[0])
|
||||
markdown.values[paperHeight] = fmt.Sprintf("%f", size[1])
|
||||
}
|
||||
|
||||
// SetMargins sets marginTop, marginBottom,
|
||||
// marginLeft and marginRight form fields.
|
||||
func (markdown *MarkdownRequest) SetMargins(margins [4]float64) {
|
||||
markdown.values[marginTop] = fmt.Sprintf("%f", margins[0])
|
||||
markdown.values[marginBottom] = fmt.Sprintf("%f", margins[1])
|
||||
markdown.values[marginLeft] = fmt.Sprintf("%f", margins[2])
|
||||
markdown.values[marginRight] = fmt.Sprintf("%f", margins[3])
|
||||
}
|
||||
|
||||
// SetLandscape sets landscape form field.
|
||||
func (markdown *MarkdownRequest) SetLandscape(isLandscape bool) {
|
||||
markdown.values[landscape] = strconv.FormatBool(isLandscape)
|
||||
}
|
||||
|
||||
func (markdown *MarkdownRequest) getPostURL() string {
|
||||
return "/convert/markdown"
|
||||
}
|
||||
|
||||
func (markdown *MarkdownRequest) getFormValues() map[string]string {
|
||||
if markdown.Options == nil {
|
||||
markdown.Options = &MarkdownOptions{}
|
||||
}
|
||||
values := make(map[string]string)
|
||||
values[webhookURL] = markdown.Options.WebHookURL
|
||||
values[paperWidth] = fmt.Sprintf("%f", markdown.Options.PaperSize[0])
|
||||
values[paperHeight] = fmt.Sprintf("%f", markdown.Options.PaperSize[1])
|
||||
values[marginTop] = fmt.Sprintf("%f", markdown.Options.PaperMargins[0])
|
||||
values[marginBottom] = fmt.Sprintf("%f", markdown.Options.PaperMargins[1])
|
||||
values[marginLeft] = fmt.Sprintf("%f", markdown.Options.PaperMargins[2])
|
||||
values[marginRight] = fmt.Sprintf("%f", markdown.Options.PaperMargins[3])
|
||||
values[landscape] = strconv.FormatBool(markdown.Options.Landscape)
|
||||
return values
|
||||
return markdown.values
|
||||
}
|
||||
|
||||
func (markdown *MarkdownRequest) getFormFiles() map[string]string {
|
||||
if markdown.Options == nil {
|
||||
markdown.Options = &MarkdownOptions{}
|
||||
}
|
||||
files := make(map[string]string)
|
||||
files["index.html"] = markdown.IndexFilePath
|
||||
files["header.html"] = markdown.Options.HeaderFilePath
|
||||
files["footer.html"] = markdown.Options.FooterFilePath
|
||||
for _, fpath := range markdown.MarkdownFilePaths {
|
||||
files["index.html"] = markdown.indexFilePath
|
||||
files["header.html"] = markdown.headerFilePath
|
||||
files["footer.html"] = markdown.footerFilePath
|
||||
for _, fpath := range markdown.markdownFilePaths {
|
||||
files[filepath.Base(fpath)] = fpath
|
||||
}
|
||||
for _, fpath := range markdown.AssetFilePaths {
|
||||
for _, fpath := range markdown.assetFilePaths {
|
||||
files[filepath.Base(fpath)] = fpath
|
||||
}
|
||||
return files
|
||||
@@ -84,4 +113,5 @@ func (markdown *MarkdownRequest) getFormFiles() map[string]string {
|
||||
// Compile-time checks to ensure type implements desired interfaces.
|
||||
var (
|
||||
_ = Request(new(MarkdownRequest))
|
||||
_ = ChromeRequest(new(MarkdownRequest))
|
||||
)
|
||||
|
||||
@@ -13,25 +13,28 @@ import (
|
||||
|
||||
func TestMarkdown(t *testing.T) {
|
||||
c := &Client{Hostname: "http://localhost:3000"}
|
||||
req := &MarkdownRequest{
|
||||
IndexFilePath: test.MarkdownTestFilePath(t, "index.html"),
|
||||
MarkdownFilePaths: []string{
|
||||
req, err := NewMarkdownRequest(
|
||||
test.MarkdownTestFilePath(t, "index.html"),
|
||||
[]string{
|
||||
test.MarkdownTestFilePath(t, "paragraph1.md"),
|
||||
test.MarkdownTestFilePath(t, "paragraph2.md"),
|
||||
test.MarkdownTestFilePath(t, "paragraph3.md"),
|
||||
},
|
||||
AssetFilePaths: []string{
|
||||
test.HTMLTestFilePath(t, "font.woff"),
|
||||
test.HTMLTestFilePath(t, "img.gif"),
|
||||
test.HTMLTestFilePath(t, "style.css"),
|
||||
},
|
||||
Options: &MarkdownOptions{
|
||||
HeaderFilePath: test.MarkdownTestFilePath(t, "header.html"),
|
||||
FooterFilePath: test.MarkdownTestFilePath(t, "footer.html"),
|
||||
PaperSize: A4,
|
||||
PaperMargins: NormalMargins,
|
||||
},
|
||||
}
|
||||
)
|
||||
require.Nil(t, err)
|
||||
err = req.SetHeader(test.MarkdownTestFilePath(t, "header.html"))
|
||||
require.Nil(t, err)
|
||||
err = req.SetFooter(test.MarkdownTestFilePath(t, "footer.html"))
|
||||
require.Nil(t, err)
|
||||
err = req.SetAssets([]string{
|
||||
test.MarkdownTestFilePath(t, "font.woff"),
|
||||
test.MarkdownTestFilePath(t, "img.gif"),
|
||||
test.MarkdownTestFilePath(t, "style.css"),
|
||||
})
|
||||
require.Nil(t, err)
|
||||
req.SetPaperSize(A4)
|
||||
req.SetMargins(NormalMargins)
|
||||
req.SetLandscape(false)
|
||||
dirPath, err := rand.Get()
|
||||
require.Nil(t, err)
|
||||
dest := fmt.Sprintf("%s/foo.pdf", dirPath)
|
||||
@@ -41,3 +44,11 @@ func TestMarkdown(t *testing.T) {
|
||||
err = os.RemoveAll(dirPath)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestConcurrentMarkdown(t *testing.T) {
|
||||
for i := 0; i < 10; i++ {
|
||||
go func() {
|
||||
TestMarkdown(t)
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
34
pkg/merge.go
34
pkg/merge.go
@@ -8,24 +8,23 @@ import (
|
||||
// MergeRequest facilitates merging PDF
|
||||
// with the Gotenberg API.
|
||||
type MergeRequest struct {
|
||||
FilePaths []string
|
||||
Options *MergeOptions
|
||||
filePaths []string
|
||||
values map[string]string
|
||||
}
|
||||
|
||||
// MergeOptions gathers all options
|
||||
// for merging PDF
|
||||
// with the Gotenberg API.
|
||||
type MergeOptions struct {
|
||||
WebHookURL string
|
||||
}
|
||||
|
||||
func (merge *MergeRequest) validate() error {
|
||||
for _, fpath := range merge.FilePaths {
|
||||
// NewMergeRequest create MergeRequest.
|
||||
func NewMergeRequest(fpaths []string) (*MergeRequest, error) {
|
||||
for _, fpath := range fpaths {
|
||||
if !fileExists(fpath) {
|
||||
return fmt.Errorf("%s: PDF file does not exist", fpath)
|
||||
return nil, fmt.Errorf("%s: file does not exist", fpath)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return &MergeRequest{filePaths: fpaths, values: make(map[string]string)}, nil
|
||||
}
|
||||
|
||||
// SetWebhookURL sets webhookURL form field.
|
||||
func (merge *MergeRequest) SetWebhookURL(webhookURL string) {
|
||||
merge.values[webhookURL] = webhookURL
|
||||
}
|
||||
|
||||
func (merge *MergeRequest) getPostURL() string {
|
||||
@@ -33,17 +32,12 @@ func (merge *MergeRequest) getPostURL() string {
|
||||
}
|
||||
|
||||
func (merge *MergeRequest) getFormValues() map[string]string {
|
||||
if merge.Options == nil {
|
||||
merge.Options = &MergeOptions{}
|
||||
}
|
||||
values := make(map[string]string)
|
||||
values[webhookURL] = merge.Options.WebHookURL
|
||||
return values
|
||||
return merge.values
|
||||
}
|
||||
|
||||
func (merge *MergeRequest) getFormFiles() map[string]string {
|
||||
files := make(map[string]string)
|
||||
for _, fpath := range merge.FilePaths {
|
||||
for _, fpath := range merge.filePaths {
|
||||
files[filepath.Base(fpath)] = fpath
|
||||
}
|
||||
return files
|
||||
|
||||
@@ -13,12 +13,11 @@ import (
|
||||
|
||||
func TestMerge(t *testing.T) {
|
||||
c := &Client{Hostname: "http://localhost:3000"}
|
||||
req := &MergeRequest{
|
||||
FilePaths: []string{
|
||||
test.PDFTestFilePath(t, "gotenberg.pdf"),
|
||||
test.PDFTestFilePath(t, "gotenberg.pdf"),
|
||||
},
|
||||
}
|
||||
req, err := NewMergeRequest([]string{
|
||||
test.PDFTestFilePath(t, "gotenberg.pdf"),
|
||||
test.PDFTestFilePath(t, "gotenberg.pdf"),
|
||||
})
|
||||
require.Nil(t, err)
|
||||
dirPath, err := rand.Get()
|
||||
require.Nil(t, err)
|
||||
dest := fmt.Sprintf("%s/foo.pdf", dirPath)
|
||||
@@ -28,3 +27,11 @@ func TestMerge(t *testing.T) {
|
||||
err = os.RemoveAll(dirPath)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestConcurrentMerge(t *testing.T) {
|
||||
for i := 0; i < 10; i++ {
|
||||
go func() {
|
||||
TestMerge(t)
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,29 +3,40 @@ package gotenberg
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// OfficeRequest facilitates Office documents
|
||||
// conversion with the Gotenberg API.
|
||||
type OfficeRequest struct {
|
||||
FilePaths []string
|
||||
Options *OfficeOptions
|
||||
filePaths []string
|
||||
values map[string]string
|
||||
}
|
||||
|
||||
// OfficeOptions gathers all options
|
||||
// for Office documents conversion
|
||||
// with the Gotenberg API.
|
||||
type OfficeOptions struct {
|
||||
WebHookURL string
|
||||
}
|
||||
|
||||
func (office *OfficeRequest) validate() error {
|
||||
for _, fpath := range office.FilePaths {
|
||||
// NewOfficeRequest create OfficeRequest.
|
||||
func NewOfficeRequest(fpaths []string) (*OfficeRequest, error) {
|
||||
for _, fpath := range fpaths {
|
||||
if !fileExists(fpath) {
|
||||
return fmt.Errorf("%s: office file does not exist", fpath)
|
||||
return nil, fmt.Errorf("%s: file does not exist", fpath)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return &OfficeRequest{filePaths: fpaths, values: make(map[string]string)}, nil
|
||||
}
|
||||
|
||||
// SetWebhookURL sets webhookURL form field.
|
||||
func (office *OfficeRequest) SetWebhookURL(webhookURL string) {
|
||||
office.values[webhookURL] = webhookURL
|
||||
}
|
||||
|
||||
// SetPaperSize sets paperWidth and paperHeight form fields.
|
||||
func (office *OfficeRequest) SetPaperSize(size [2]float64) {
|
||||
office.values[paperWidth] = fmt.Sprintf("%f", size[0])
|
||||
office.values[paperHeight] = fmt.Sprintf("%f", size[1])
|
||||
}
|
||||
|
||||
// SetLandscape sets landscape form field.
|
||||
func (office *OfficeRequest) SetLandscape(isLandscape bool) {
|
||||
office.values[landscape] = strconv.FormatBool(isLandscape)
|
||||
}
|
||||
|
||||
func (office *OfficeRequest) getPostURL() string {
|
||||
@@ -33,17 +44,12 @@ func (office *OfficeRequest) getPostURL() string {
|
||||
}
|
||||
|
||||
func (office *OfficeRequest) getFormValues() map[string]string {
|
||||
if office.Options == nil {
|
||||
office.Options = &OfficeOptions{}
|
||||
}
|
||||
values := make(map[string]string)
|
||||
values[webhookURL] = office.Options.WebHookURL
|
||||
return values
|
||||
return office.values
|
||||
}
|
||||
|
||||
func (office *OfficeRequest) getFormFiles() map[string]string {
|
||||
files := make(map[string]string)
|
||||
for _, fpath := range office.FilePaths {
|
||||
for _, fpath := range office.filePaths {
|
||||
files[filepath.Base(fpath)] = fpath
|
||||
}
|
||||
return files
|
||||
@@ -52,4 +58,5 @@ func (office *OfficeRequest) getFormFiles() map[string]string {
|
||||
// Compile-time checks to ensure type implements desired interfaces.
|
||||
var (
|
||||
_ = Request(new(OfficeRequest))
|
||||
_ = UnoconvRequest(new(OfficeRequest))
|
||||
)
|
||||
|
||||
@@ -13,11 +13,12 @@ import (
|
||||
|
||||
func TestOffice(t *testing.T) {
|
||||
c := &Client{Hostname: "http://localhost:3000"}
|
||||
req := &OfficeRequest{
|
||||
FilePaths: []string{
|
||||
test.OfficeTestFilePath(t, "document.docx"),
|
||||
},
|
||||
}
|
||||
req, err := NewOfficeRequest([]string{
|
||||
test.OfficeTestFilePath(t, "document.docx"),
|
||||
})
|
||||
require.Nil(t, err)
|
||||
req.SetPaperSize(A4)
|
||||
req.SetLandscape(false)
|
||||
dirPath, err := rand.Get()
|
||||
require.Nil(t, err)
|
||||
dest := fmt.Sprintf("%s/foo.pdf", dirPath)
|
||||
@@ -27,3 +28,11 @@ func TestOffice(t *testing.T) {
|
||||
err = os.RemoveAll(dirPath)
|
||||
assert.Nil(t, err)
|
||||
}
|
||||
|
||||
func TestConcurrentOffice(t *testing.T) {
|
||||
for i := 0; i < 10; i++ {
|
||||
go func() {
|
||||
TestOffice(t)
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
2196
test/testdata/office/document.rtf
vendored
Normal file
2196
test/testdata/office/document.rtf
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3
test/testdata/office/document.txt
vendored
Normal file
3
test/testdata/office/document.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
Gutenberg
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
BIN
test/testdata/pdf/gotenberg_bis.pdf
vendored
Normal file
BIN
test/testdata/pdf/gotenberg_bis.pdf
vendored
Normal file
Binary file not shown.
@@ -16,31 +16,31 @@ import (
|
||||
"github.com/thecodingmachine/gotenberg/internal/pkg/rand"
|
||||
)
|
||||
|
||||
// HTMLMultipartForm returns the body
|
||||
// HTMLTestMultipartForm returns the body
|
||||
// for a multipate/form-data request with all
|
||||
// files under "html" folder.
|
||||
func HTMLMultipartForm(t *testing.T) (*bytes.Buffer, string) {
|
||||
func HTMLTestMultipartForm(t *testing.T) (*bytes.Buffer, string) {
|
||||
return multipartForm(t, "html")
|
||||
}
|
||||
|
||||
// MarkdownMultipartForm returns the body
|
||||
// MarkdownTestMultipartForm returns the body
|
||||
// for a multipate/form-data request with all
|
||||
// files under "markdown" folder.
|
||||
func MarkdownMultipartForm(t *testing.T) (*bytes.Buffer, string) {
|
||||
func MarkdownTestMultipartForm(t *testing.T) (*bytes.Buffer, string) {
|
||||
return multipartForm(t, "markdown")
|
||||
}
|
||||
|
||||
// OfficeMultipartForm returns the body
|
||||
// OfficeTestMultipartForm returns the body
|
||||
// for a multipate/form-data request with all
|
||||
// files under "office" folder.
|
||||
func OfficeMultipartForm(t *testing.T) (*bytes.Buffer, string) {
|
||||
func OfficeTestMultipartForm(t *testing.T) (*bytes.Buffer, string) {
|
||||
return multipartForm(t, "office")
|
||||
}
|
||||
|
||||
// PDFMultipartForm returns the body
|
||||
// PDFTestMultipartForm returns the body
|
||||
// for a multipate/form-data request with all
|
||||
// files under "pdf" folder.
|
||||
func PDFMultipartForm(t *testing.T) (*bytes.Buffer, string) {
|
||||
func PDFTestMultipartForm(t *testing.T) (*bytes.Buffer, string) {
|
||||
return multipartForm(t, "pdf")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user