now using latest version of unoconv, allowing to specify paper size and orientation + updating go client (#24)

This commit is contained in:
Julien Neuhart
2018-12-12 16:16:35 +01:00
committed by GitHub
parent 1ef21c6ed6
commit c6f6a87499
19 changed files with 466 additions and 308 deletions

View File

@@ -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 &&\ RUN echo "deb http://httpredir.debian.org/debian/ stretch main contrib non-free" > /etc/apt/sources.list &&\
apt-get update &&\ apt-get update &&\
apt-get install -y curl wget apt-get install -y curl wget python3-pip
# |-------------------------------------------------------------------------- # |--------------------------------------------------------------------------
# | PM2 # | PM2
@@ -39,7 +39,10 @@ RUN wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add
# | Unoconv # | 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

View File

@@ -43,9 +43,7 @@ import "github.com/thecodingmachine/gotenberg/pkg"
func main() { func main() {
c := &gotenberg.Client{Hostname: "http://localhost:3000"} c := &gotenberg.Client{Hostname: "http://localhost:3000"}
req := &gotenberg.HTMLRequest{ req, _ := gotenberg.NewHTMLRequest("index.html")
IndexFilePath: "index.html",
}
dest := "result.pdf" dest := "result.pdf"
c.Store(req, dest) c.Store(req, dest)
} }
@@ -119,13 +117,9 @@ import "github.com/thecodingmachine/gotenberg/pkg"
func main() { func main() {
c := &gotenberg.Client{Hostname: "http://localhost:3000"} c := &gotenberg.Client{Hostname: "http://localhost:3000"}
req := &gotenberg.HTMLRequest{ req, _ := gotenberg.NewHTMLRequest("index.html")
IndexFilePath: "index.html", req.SetHeader("header.html")
Options: &gotenberg.HTMLOptions{ req.SetFooter("footer.html")
HeaderFilePath: "header.html",
FooterFilePath: "footer.html",
},
}
dest := "result.pdf" dest := "result.pdf"
c.Store(req, dest) c.Store(req, dest)
} }
@@ -213,14 +207,12 @@ import "github.com/thecodingmachine/gotenberg/pkg"
func main() { func main() {
c := &gotenberg.Client{Hostname: "http://localhost:3000"} c := &gotenberg.Client{Hostname: "http://localhost:3000"}
req := &gotenberg.HTMLRequest{ req, _ := gotenberg.NewHTMLRequest("index.html")
IndexFilePath: "index.html", req.SetAssets([]string{
AssetFilePaths: []string{ "font.woff",
"style.css", "img.gif",
"img.png", "style.css",
"font.woff", })
},
}
dest := "result.pdf" dest := "result.pdf"
c.Store(req, dest) c.Store(req, dest)
} }
@@ -279,14 +271,10 @@ import "github.com/thecodingmachine/gotenberg/pkg"
func main() { func main() {
c := &gotenberg.Client{Hostname: "http://localhost:3000"} c := &gotenberg.Client{Hostname: "http://localhost:3000"}
req := &gotenberg.HTMLRequest{ req, _ := gotenberg.NewHTMLRequest("index.html")
IndexFilePath: "index.html", req.SetPaperSize(gotenberg.A4)
Options: &gotenberg.HTMLOptions{ req.SetMargins(gotenberg.NormalMargins)
PaperSize: gotenberg.A4, req.SetLandscape(true)
PaperMargins: gotenberg.NoMargins,
Landscape: true
},
}
dest := "result.pdf" dest := "result.pdf"
c.Store(req, dest) c.Store(req, dest)
} }

View File

@@ -46,12 +46,7 @@ import "github.com/thecodingmachine/gotenberg/pkg"
func main() { func main() {
c := &gotenberg.Client{Hostname: "http://localhost:3000"} c := &gotenberg.Client{Hostname: "http://localhost:3000"}
req := &gotenberg.MarkdownRequest{ req, _ := gotenberg.NewMarkdownRequest("index.html", []string{"file.md"})
IndexFilePath: "index.html",
MarkdownFilePaths: []string{
"file.md",
},
}
dest := "result.pdf" dest := "result.pdf"
c.Store(req, dest) c.Store(req, dest)
} }

View File

@@ -44,12 +44,7 @@ import "github.com/thecodingmachine/gotenberg/pkg"
func main() { func main() {
c := &gotenberg.Client{Hostname: "http://localhost:3000"} c := &gotenberg.Client{Hostname: "http://localhost:3000"}
req := &gotenberg.OfficeRequest{ req, _ := gotenberg.NewOfficeRequest([]string{"document.docx", "document2.docx"})
FilePaths: []string{
"document.docx",
"document2.docx",
},
}
dest := "result.pdf" dest := "result.pdf"
c.Store(req, dest) c.Store(req, dest)
} }
@@ -72,6 +67,62 @@ $dirPath = "/foo";
$filename = $client->store($request, $dirPath); $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 `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(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->setMargins(Request::NO_MARGINS);
$request->setLandscape(true);
$dirPath = "/foo";
$filename = $client->store($request, $dirPath);
```
## Fonts ## Fonts
By default, only `ttf-mscorefonts` fonts are installed. By default, only `ttf-mscorefonts` fonts are installed.

View File

@@ -29,12 +29,7 @@ import "github.com/thecodingmachine/gotenberg/pkg"
func main() { func main() {
c := &gotenberg.Client{Hostname: "http://localhost:3000"} c := &gotenberg.Client{Hostname: "http://localhost:3000"}
req := &gotenberg.MergeRequest{ req, _ := gotenberg.NewMergeRequest([]string{"file.pdf", "file2.pdf"})
FilePaths: []string{
"file.pdf",
"file2.pdf",
},
}
dest := "result.pdf" dest := "result.pdf"
c.Store(req, dest) c.Store(req, dest)
} }

View File

@@ -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="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">&amp;</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">&#34;http://localhost:3000&#34;</span><span class="p">}</span> <span class="nx">c</span> <span class="o">:=</span> <span class="o">&amp;</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">&#34;http://localhost:3000&#34;</span><span class="p">}</span>
<span class="nx">req</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">HTMLRequest</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">&#34;index.html&#34;</span><span class="p">)</span>
<span class="nx">IndexFilePath</span><span class="p">:</span> <span class="s">&#34;index.html&#34;</span><span class="p">,</span>
<span class="p">}</span>
<span class="nx">dest</span> <span class="o">:=</span> <span class="s">&#34;result.pdf&#34;</span> <span class="nx">dest</span> <span class="o">:=</span> <span class="s">&#34;result.pdf&#34;</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="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> <span class="p">}</span>
@@ -271,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="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">&amp;</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">&#34;http://localhost:3000&#34;</span><span class="p">}</span> <span class="nx">c</span> <span class="o">:=</span> <span class="o">&amp;</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">&#34;http://localhost:3000&#34;</span><span class="p">}</span>
<span class="nx">req</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">HTMLRequest</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">&#34;index.html&#34;</span><span class="p">)</span>
<span class="nx">IndexFilePath</span><span class="p">:</span> <span class="s">&#34;index.html&#34;</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">&#34;header.html&#34;</span><span class="p">)</span>
<span class="nx">Options</span><span class="p">:</span> <span class="o">&amp;</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">HTMLOptions</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">&#34;footer.html&#34;</span><span class="p">)</span>
<span class="nx">HeaderFilePath</span><span class="p">:</span> <span class="s">&#34;header.html&#34;</span><span class="p">,</span>
<span class="nx">FooterFilePath</span><span class="p">:</span> <span class="s">&#34;footer.html&#34;</span><span class="p">,</span>
<span class="p">},</span>
<span class="p">}</span>
<span class="nx">dest</span> <span class="o">:=</span> <span class="s">&#34;result.pdf&#34;</span> <span class="nx">dest</span> <span class="o">:=</span> <span class="s">&#34;result.pdf&#34;</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="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> <span class="p">}</span>
@@ -370,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="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">&amp;</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">&#34;http://localhost:3000&#34;</span><span class="p">}</span> <span class="nx">c</span> <span class="o">:=</span> <span class="o">&amp;</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">&#34;http://localhost:3000&#34;</span><span class="p">}</span>
<span class="nx">req</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">HTMLRequest</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">&#34;index.html&#34;</span><span class="p">)</span>
<span class="nx">IndexFilePath</span><span class="p">:</span> <span class="s">&#34;index.html&#34;</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="nx">AssetFilePaths</span><span class="p">:</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span> <span class="s">&#34;font.woff&#34;</span><span class="p">,</span>
<span class="s">&#34;style.css&#34;</span><span class="p">,</span> <span class="s">&#34;img.gif&#34;</span><span class="p">,</span>
<span class="s">&#34;img.png&#34;</span><span class="p">,</span> <span class="s">&#34;style.css&#34;</span><span class="p">,</span>
<span class="s">&#34;font.woff&#34;</span><span class="p">,</span> <span class="p">})</span>
<span class="p">},</span>
<span class="p">}</span>
<span class="nx">dest</span> <span class="o">:=</span> <span class="s">&#34;result.pdf&#34;</span> <span class="nx">dest</span> <span class="o">:=</span> <span class="s">&#34;result.pdf&#34;</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="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> <span class="p">}</span>
@@ -443,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="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">&amp;</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">&#34;http://localhost:3000&#34;</span><span class="p">}</span> <span class="nx">c</span> <span class="o">:=</span> <span class="o">&amp;</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">&#34;http://localhost:3000&#34;</span><span class="p">}</span>
<span class="nx">req</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">HTMLRequest</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">&#34;index.html&#34;</span><span class="p">)</span>
<span class="nx">IndexFilePath</span><span class="p">:</span> <span class="s">&#34;index.html&#34;</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">Options</span><span class="p">:</span> <span class="o">&amp;</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">HTMLOptions</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">NormalMargins</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">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">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">dest</span> <span class="o">:=</span> <span class="s">&#34;result.pdf&#34;</span> <span class="nx">dest</span> <span class="o">:=</span> <span class="s">&#34;result.pdf&#34;</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="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> <span class="p">}</span>
@@ -528,12 +516,7 @@ in the file <code>index.html</code>. This function will convert a given markdown
<span class="kd">func</span> <span class="nx">main</span><span class="p">()</span> <span class="p">{</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">&amp;</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">&#34;http://localhost:3000&#34;</span><span class="p">}</span> <span class="nx">c</span> <span class="o">:=</span> <span class="o">&amp;</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">&#34;http://localhost:3000&#34;</span><span class="p">}</span>
<span class="nx">req</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">MarkdownRequest</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">&#34;index.html&#34;</span><span class="p">,</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">&#34;file.md&#34;</span><span class="p">})</span>
<span class="nx">IndexFilePath</span><span class="p">:</span> <span class="s">&#34;index.html&#34;</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">&#34;file.md&#34;</span><span class="p">,</span>
<span class="p">},</span>
<span class="p">}</span>
<span class="nx">dest</span> <span class="o">:=</span> <span class="s">&#34;result.pdf&#34;</span> <span class="nx">dest</span> <span class="o">:=</span> <span class="s">&#34;result.pdf&#34;</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="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> <span class="p">}</span>
@@ -613,12 +596,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="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">&amp;</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">&#34;http://localhost:3000&#34;</span><span class="p">}</span> <span class="nx">c</span> <span class="o">:=</span> <span class="o">&amp;</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">&#34;http://localhost:3000&#34;</span><span class="p">}</span>
<span class="nx">req</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">OfficeRequest</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">&#34;document.docx&#34;</span><span class="p">,</span> <span class="s">&#34;document2.docx&#34;</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">&#34;document.docx&#34;</span><span class="p">,</span>
<span class="s">&#34;document2.docx&#34;</span><span class="p">,</span>
<span class="p">},</span>
<span class="p">}</span>
<span class="nx">dest</span> <span class="o">:=</span> <span class="s">&#34;result.pdf&#34;</span> <span class="nx">dest</span> <span class="o">:=</span> <span class="s">&#34;result.pdf&#34;</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="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> <span class="p">}</span>
@@ -642,6 +620,69 @@ See the <a href="#scalability">scalability section</a> to find how to mitigate t
</span><span class="x">$filename = $client-&gt;store($request, $dirPath); </span><span class="x">$filename = $client-&gt;store($request, $dirPath);
</span><span class="x"></span></pre> </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 <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">&#39;Content-Type: multipart/form-data&#39;</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> &gt; 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">&#34;github.com/thecodingmachine/gotenberg/pkg&#34;</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">&amp;</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">&#34;http://localhost:3000&#34;</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">&#34;document.docx&#34;</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">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">&#34;result.pdf&#34;</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(&#39;http://localhost:3000&#39;, new \Http\Adapter\Guzzle6\Client());
</span><span class="x">$files = [
</span><span class="x"> DocumentFactory::makeFromPath(&#39;document.docx&#39;, &#39;document.docx&#39;),
</span><span class="x">];
</span><span class="x">$request = new OfficeRequest($files);
</span><span class="x">$request-&gt;setPaperSize(Request::A4);
</span><span class="x">$request-&gt;setMargins(Request::NO_MARGINS);
</span><span class="x">$request-&gt;setLandscape(true);
</span><span class="x">$dirPath = &#34;/foo&#34;;
</span><span class="x">$filename = $client-&gt;store($request, $dirPath);
</span><span class="x"></span></pre>
<h2 class="Heading"><a class="Anchor" aria-hidden="true" id="office.fonts" href="#office.fonts"> <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> <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>Fonts</h2> </a>Fonts</h2>
@@ -692,12 +733,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="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">&amp;</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">&#34;http://localhost:3000&#34;</span><span class="p">}</span> <span class="nx">c</span> <span class="o">:=</span> <span class="o">&amp;</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">&#34;http://localhost:3000&#34;</span><span class="p">}</span>
<span class="nx">req</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">gotenberg</span><span class="p">.</span><span class="nx">MergeRequest</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">&#34;file.pdf&#34;</span><span class="p">,</span> <span class="s">&#34;file2.pdf&#34;</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">&#34;file.pdf&#34;</span><span class="p">,</span>
<span class="s">&#34;file2.pdf&#34;</span><span class="p">,</span>
<span class="p">},</span>
<span class="p">}</span>
<span class="nx">dest</span> <span class="o">:=</span> <span class="s">&#34;result.pdf&#34;</span> <span class="nx">dest</span> <span class="o">:=</span> <span class="s">&#34;result.pdf&#34;</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="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> <span class="p">}</span>

View File

@@ -37,5 +37,16 @@ func convertOffice(c echo.Context) error {
return errors.New("no suitable office documents to convert") return errors.New("no suitable office documents to convert")
} }
p := &printer.Office{Context: ctx, FilePaths: fpaths} p := &printer.Office{Context: ctx, FilePaths: fpaths}
paperSize, err := r.paperSize()
if err != nil {
return err
}
p.PaperWidth = paperSize[0]
p.PaperHeight = paperSize[1]
landscape, err := r.landscape()
if err != nil {
return err
}
p.Landscape = landscape
return print(c, p, r) return print(c, p, r)
} }

View File

@@ -7,6 +7,7 @@ import (
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"strconv"
"sync" "sync"
"github.com/thecodingmachine/gotenberg/internal/pkg/rand" "github.com/thecodingmachine/gotenberg/internal/pkg/rand"
@@ -16,8 +17,11 @@ var mu sync.Mutex
// Office facilitates Office documents to PDF conversion. // Office facilitates Office documents to PDF conversion.
type Office struct { type Office struct {
Context context.Context Context context.Context
FilePaths []string FilePaths []string
PaperWidth float64
PaperHeight float64
Landscape bool
} }
// Print converts Office documents to PDF. // Print converts Office documents to PDF.
@@ -32,14 +36,24 @@ func (o *Office) Print(destination string) error {
return err return err
} }
tmpDest := fmt.Sprintf("%s/%s.pdf", dirPath, baseFilename) 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( cmd := exec.CommandContext(
o.Context, o.Context,
"unoconv", "unoconv",
"--format", cmdArgs...,
"pdf",
"--output",
tmpDest,
fpath,
) )
_, err = cmd.Output() _, err = cmd.Output()
if o.Context.Err() == context.DeadlineExceeded { if o.Context.Err() == context.DeadlineExceeded {
@@ -56,6 +70,18 @@ func (o *Office) Print(destination string) error {
return Merge(fpaths, destination) 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. // Compile-time checks to ensure type implements desired interfaces.
var ( var (
_ = Printer(new(Office)) _ = Printer(new(Office))

View File

@@ -16,19 +16,17 @@ import "github.com/thecodingmachine/gotenberg/pkg"
func main() { func main() {
// HTML conversion example. // HTML conversion example.
c := &gotenberg.Client{Hostname: "http://localhost:3000"} c := &gotenberg.Client{Hostname: "http://localhost:3000"}
req := &gotenberg.HTMLRequest{ req, _ := gotenberg.NewHTMLRequest("index.html")
IndexFilePath: "index.html", req.SetHeader("header.html")
AssetFilePaths: []string{ req.SetFooter("footer.html")
"style.css", req.SetAssets([]string{
"img.png", "font.woff",
}, "img.gif",
Options: &gotenberg.HTMLOptions{ "style.css",
HeaderFilePath: "header.html", })
FooterFilePath: "footer.html", req.SetPaperSize(A4)
PaperSize: gotenberg.A4, req.SetMargins(NormalMargins)
PaperMargins: gotenberg.NormalMargins, req.SetLandscape(false)
},
}
dest := "foo.pdf" dest := "foo.pdf"
c.Store(req, dest) c.Store(req, dest)
} }

View File

@@ -59,18 +59,35 @@ type Client struct {
// form values and form files to // form values and form files to
// the Gotenberg API. // the Gotenberg API.
type Request interface { type Request interface {
validate() error SetWebhookURL(webhookURL string)
getPostURL() string getPostURL() string
getFormValues() map[string]string getFormValues() map[string]string
getFormFiles() 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 // Post sends a request to the Gotenberg API
// and returns the response. // and returns the response.
func (c *Client) Post(req Request) (*http.Response, error) { func (c *Client) Post(req Request) (*http.Response, error) {
if err := req.validate(); err != nil {
return nil, err
}
body, contentType, err := multipartForm(req) body, contentType, err := multipartForm(req)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -2,30 +2,7 @@
Package gotenberg is a Go client for Package gotenberg is a Go client for
interacting with a Gotenberg API. interacting with a Gotenberg API.
For instance, if you want to convert HTML: For more complete usages, head to the documentation:
https://thecodingmachine.gotenberg.github.io.
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.
*/ */
package gotenberg package gotenberg

View File

@@ -9,64 +9,89 @@ import (
// HTMLRequest facilitates HTML conversion // HTMLRequest facilitates HTML conversion
// with the Gotenberg API. // with the Gotenberg API.
type HTMLRequest struct { type HTMLRequest struct {
IndexFilePath string indexFilePath string
AssetFilePaths []string headerFilePath string
Options *HTMLOptions footerFilePath string
assetFilePaths []string
values map[string]string
} }
// HTMLOptions gathers all options // NewHTMLRequest create HTMLRequest.
// for HTML conversion with the Gotenberg API. func NewHTMLRequest(indexFilePath string) (*HTMLRequest, error) {
type HTMLOptions struct { if !fileExists(indexFilePath) {
WebHookURL string return nil, fmt.Errorf("%s: index file does not exist", indexFilePath)
HeaderFilePath string }
FooterFilePath string return &HTMLRequest{indexFilePath: indexFilePath, values: make(map[string]string)}, nil
PaperSize [2]float64
PaperMargins [4]float64
Landscape bool
} }
func (html *HTMLRequest) validate() error { // SetWebhookURL sets webhookURL form field.
if !fileExists(html.IndexFilePath) { func (html *HTMLRequest) SetWebhookURL(webhookURL string) {
return fmt.Errorf("%s: index file does not exist", html.IndexFilePath) html.values[webhookURL] = webhookURL
} }
if html.Options.HeaderFilePath != "" && !fileExists(html.Options.HeaderFilePath) {
return fmt.Errorf("%s: header file does not exist", html.Options.HeaderFilePath) // SetHeader sets header form file.
} func (html *HTMLRequest) SetHeader(fpath string) error {
if html.Options.FooterFilePath != "" && !fileExists(html.Options.FooterFilePath) { if !fileExists(fpath) {
return fmt.Errorf("%s: footer file does not exist", html.Options.FooterFilePath) return fmt.Errorf("%s: header file does not exist", fpath)
} }
html.headerFilePath = fpath
return nil 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 { func (html *HTMLRequest) getPostURL() string {
return "/convert/html" return "/convert/html"
} }
func (html *HTMLRequest) getFormValues() map[string]string { func (html *HTMLRequest) getFormValues() map[string]string {
if html.Options == nil { return html.values
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
} }
func (html *HTMLRequest) getFormFiles() map[string]string { func (html *HTMLRequest) getFormFiles() map[string]string {
if html.Options == nil {
html.Options = &HTMLOptions{}
}
files := make(map[string]string) files := make(map[string]string)
files["index.html"] = html.IndexFilePath files["index.html"] = html.indexFilePath
files["header.html"] = html.Options.HeaderFilePath files["header.html"] = html.headerFilePath
files["footer.html"] = html.Options.FooterFilePath files["footer.html"] = html.footerFilePath
for _, fpath := range html.AssetFilePaths { for _, fpath := range html.assetFilePaths {
files[filepath.Base(fpath)] = fpath files[filepath.Base(fpath)] = fpath
} }
return files return files
@@ -75,4 +100,5 @@ func (html *HTMLRequest) getFormFiles() map[string]string {
// Compile-time checks to ensure type implements desired interfaces. // Compile-time checks to ensure type implements desired interfaces.
var ( var (
_ = Request(new(HTMLRequest)) _ = Request(new(HTMLRequest))
_ = ChromeRequest(new(HTMLRequest))
) )

View File

@@ -13,20 +13,21 @@ import (
func TestHTML(t *testing.T) { func TestHTML(t *testing.T) {
c := &Client{Hostname: "http://localhost:3000"} c := &Client{Hostname: "http://localhost:3000"}
req := &HTMLRequest{ req, err := NewHTMLRequest(test.HTMLTestFilePath(t, "index.html"))
IndexFilePath: test.HTMLTestFilePath(t, "index.html"), require.Nil(t, err)
AssetFilePaths: []string{ err = req.SetHeader(test.HTMLTestFilePath(t, "header.html"))
test.HTMLTestFilePath(t, "font.woff"), require.Nil(t, err)
test.HTMLTestFilePath(t, "img.gif"), err = req.SetFooter(test.HTMLTestFilePath(t, "footer.html"))
test.HTMLTestFilePath(t, "style.css"), require.Nil(t, err)
}, err = req.SetAssets([]string{
Options: &HTMLOptions{ test.HTMLTestFilePath(t, "font.woff"),
HeaderFilePath: test.HTMLTestFilePath(t, "header.html"), test.HTMLTestFilePath(t, "img.gif"),
FooterFilePath: test.HTMLTestFilePath(t, "footer.html"), test.HTMLTestFilePath(t, "style.css"),
PaperSize: A4, })
PaperMargins: NormalMargins, require.Nil(t, err)
}, req.SetPaperSize(A4)
} req.SetMargins(NormalMargins)
req.SetLandscape(false)
dirPath, err := rand.Get() dirPath, err := rand.Get()
require.Nil(t, err) require.Nil(t, err)
dest := fmt.Sprintf("%s/foo.pdf", dirPath) dest := fmt.Sprintf("%s/foo.pdf", dirPath)

View File

@@ -9,73 +9,102 @@ import (
// MarkdownRequest facilitates Markdown conversion // MarkdownRequest facilitates Markdown conversion
// with the Gotenberg API. // with the Gotenberg API.
type MarkdownRequest struct { type MarkdownRequest struct {
IndexFilePath string indexFilePath string
MarkdownFilePaths []string markdownFilePaths []string
AssetFilePaths []string headerFilePath string
Options *MarkdownOptions footerFilePath string
assetFilePaths []string
values map[string]string
} }
// MarkdownOptions gathers all options // NewMarkdownRequest create MarkdownRequest.
// for Markdown conversion with the Gotenberg API. func NewMarkdownRequest(indexFilePath string, markdownFilePaths []string) (*MarkdownRequest, error) {
type MarkdownOptions struct { if !fileExists(indexFilePath) {
WebHookURL string return nil, fmt.Errorf("%s: index file does not exist", indexFilePath)
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)
} }
if markdown.Options.HeaderFilePath != "" && !fileExists(markdown.Options.HeaderFilePath) { for _, fpath := range markdownFilePaths {
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 {
if !fileExists(fpath) { 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 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 { func (markdown *MarkdownRequest) getPostURL() string {
return "/convert/markdown" return "/convert/markdown"
} }
func (markdown *MarkdownRequest) getFormValues() map[string]string { func (markdown *MarkdownRequest) getFormValues() map[string]string {
if markdown.Options == nil { return markdown.values
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
} }
func (markdown *MarkdownRequest) getFormFiles() map[string]string { func (markdown *MarkdownRequest) getFormFiles() map[string]string {
if markdown.Options == nil {
markdown.Options = &MarkdownOptions{}
}
files := make(map[string]string) files := make(map[string]string)
files["index.html"] = markdown.IndexFilePath files["index.html"] = markdown.indexFilePath
files["header.html"] = markdown.Options.HeaderFilePath files["header.html"] = markdown.headerFilePath
files["footer.html"] = markdown.Options.FooterFilePath files["footer.html"] = markdown.footerFilePath
for _, fpath := range markdown.MarkdownFilePaths { for _, fpath := range markdown.markdownFilePaths {
files[filepath.Base(fpath)] = fpath files[filepath.Base(fpath)] = fpath
} }
for _, fpath := range markdown.AssetFilePaths { for _, fpath := range markdown.assetFilePaths {
files[filepath.Base(fpath)] = fpath files[filepath.Base(fpath)] = fpath
} }
return files return files
@@ -84,4 +113,5 @@ func (markdown *MarkdownRequest) getFormFiles() map[string]string {
// Compile-time checks to ensure type implements desired interfaces. // Compile-time checks to ensure type implements desired interfaces.
var ( var (
_ = Request(new(MarkdownRequest)) _ = Request(new(MarkdownRequest))
_ = ChromeRequest(new(MarkdownRequest))
) )

View File

@@ -13,25 +13,28 @@ import (
func TestMarkdown(t *testing.T) { func TestMarkdown(t *testing.T) {
c := &Client{Hostname: "http://localhost:3000"} c := &Client{Hostname: "http://localhost:3000"}
req := &MarkdownRequest{ req, err := NewMarkdownRequest(
IndexFilePath: test.MarkdownTestFilePath(t, "index.html"), test.MarkdownTestFilePath(t, "index.html"),
MarkdownFilePaths: []string{ []string{
test.MarkdownTestFilePath(t, "paragraph1.md"), test.MarkdownTestFilePath(t, "paragraph1.md"),
test.MarkdownTestFilePath(t, "paragraph2.md"), test.MarkdownTestFilePath(t, "paragraph2.md"),
test.MarkdownTestFilePath(t, "paragraph3.md"), test.MarkdownTestFilePath(t, "paragraph3.md"),
}, },
AssetFilePaths: []string{ )
test.HTMLTestFilePath(t, "font.woff"), require.Nil(t, err)
test.HTMLTestFilePath(t, "img.gif"), err = req.SetHeader(test.MarkdownTestFilePath(t, "header.html"))
test.HTMLTestFilePath(t, "style.css"), require.Nil(t, err)
}, err = req.SetFooter(test.MarkdownTestFilePath(t, "footer.html"))
Options: &MarkdownOptions{ require.Nil(t, err)
HeaderFilePath: test.MarkdownTestFilePath(t, "header.html"), err = req.SetAssets([]string{
FooterFilePath: test.MarkdownTestFilePath(t, "footer.html"), test.MarkdownTestFilePath(t, "font.woff"),
PaperSize: A4, test.MarkdownTestFilePath(t, "img.gif"),
PaperMargins: NormalMargins, test.MarkdownTestFilePath(t, "style.css"),
}, })
} require.Nil(t, err)
req.SetPaperSize(A4)
req.SetMargins(NormalMargins)
req.SetLandscape(false)
dirPath, err := rand.Get() dirPath, err := rand.Get()
require.Nil(t, err) require.Nil(t, err)
dest := fmt.Sprintf("%s/foo.pdf", dirPath) dest := fmt.Sprintf("%s/foo.pdf", dirPath)

View File

@@ -8,24 +8,23 @@ import (
// MergeRequest facilitates merging PDF // MergeRequest facilitates merging PDF
// with the Gotenberg API. // with the Gotenberg API.
type MergeRequest struct { type MergeRequest struct {
FilePaths []string filePaths []string
Options *MergeOptions values map[string]string
} }
// MergeOptions gathers all options // NewMergeRequest create MergeRequest.
// for merging PDF func NewMergeRequest(fpaths []string) (*MergeRequest, error) {
// with the Gotenberg API. for _, fpath := range fpaths {
type MergeOptions struct {
WebHookURL string
}
func (merge *MergeRequest) validate() error {
for _, fpath := range merge.FilePaths {
if !fileExists(fpath) { 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 { func (merge *MergeRequest) getPostURL() string {
@@ -33,17 +32,12 @@ func (merge *MergeRequest) getPostURL() string {
} }
func (merge *MergeRequest) getFormValues() map[string]string { func (merge *MergeRequest) getFormValues() map[string]string {
if merge.Options == nil { return merge.values
merge.Options = &MergeOptions{}
}
values := make(map[string]string)
values[webhookURL] = merge.Options.WebHookURL
return values
} }
func (merge *MergeRequest) getFormFiles() map[string]string { func (merge *MergeRequest) getFormFiles() map[string]string {
files := make(map[string]string) files := make(map[string]string)
for _, fpath := range merge.FilePaths { for _, fpath := range merge.filePaths {
files[filepath.Base(fpath)] = fpath files[filepath.Base(fpath)] = fpath
} }
return files return files

View File

@@ -13,12 +13,11 @@ import (
func TestMerge(t *testing.T) { func TestMerge(t *testing.T) {
c := &Client{Hostname: "http://localhost:3000"} c := &Client{Hostname: "http://localhost:3000"}
req := &MergeRequest{ req, err := NewMergeRequest([]string{
FilePaths: []string{ test.PDFTestFilePath(t, "gotenberg.pdf"),
test.PDFTestFilePath(t, "gotenberg.pdf"), test.PDFTestFilePath(t, "gotenberg.pdf"),
test.PDFTestFilePath(t, "gotenberg.pdf"), })
}, require.Nil(t, err)
}
dirPath, err := rand.Get() dirPath, err := rand.Get()
require.Nil(t, err) require.Nil(t, err)
dest := fmt.Sprintf("%s/foo.pdf", dirPath) dest := fmt.Sprintf("%s/foo.pdf", dirPath)

View File

@@ -3,29 +3,40 @@ package gotenberg
import ( import (
"fmt" "fmt"
"path/filepath" "path/filepath"
"strconv"
) )
// OfficeRequest facilitates Office documents // OfficeRequest facilitates Office documents
// conversion with the Gotenberg API. // conversion with the Gotenberg API.
type OfficeRequest struct { type OfficeRequest struct {
FilePaths []string filePaths []string
Options *OfficeOptions values map[string]string
} }
// OfficeOptions gathers all options // NewOfficeRequest create OfficeRequest.
// for Office documents conversion func NewOfficeRequest(fpaths []string) (*OfficeRequest, error) {
// with the Gotenberg API. for _, fpath := range fpaths {
type OfficeOptions struct {
WebHookURL string
}
func (office *OfficeRequest) validate() error {
for _, fpath := range office.FilePaths {
if !fileExists(fpath) { 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 { func (office *OfficeRequest) getPostURL() string {
@@ -33,17 +44,12 @@ func (office *OfficeRequest) getPostURL() string {
} }
func (office *OfficeRequest) getFormValues() map[string]string { func (office *OfficeRequest) getFormValues() map[string]string {
if office.Options == nil { return office.values
office.Options = &OfficeOptions{}
}
values := make(map[string]string)
values[webhookURL] = office.Options.WebHookURL
return values
} }
func (office *OfficeRequest) getFormFiles() map[string]string { func (office *OfficeRequest) getFormFiles() map[string]string {
files := make(map[string]string) files := make(map[string]string)
for _, fpath := range office.FilePaths { for _, fpath := range office.filePaths {
files[filepath.Base(fpath)] = fpath files[filepath.Base(fpath)] = fpath
} }
return files return files
@@ -52,4 +58,5 @@ func (office *OfficeRequest) getFormFiles() map[string]string {
// Compile-time checks to ensure type implements desired interfaces. // Compile-time checks to ensure type implements desired interfaces.
var ( var (
_ = Request(new(OfficeRequest)) _ = Request(new(OfficeRequest))
_ = UnoconvRequest(new(OfficeRequest))
) )

View File

@@ -13,11 +13,12 @@ import (
func TestOffice(t *testing.T) { func TestOffice(t *testing.T) {
c := &Client{Hostname: "http://localhost:3000"} c := &Client{Hostname: "http://localhost:3000"}
req := &OfficeRequest{ req, err := NewOfficeRequest([]string{
FilePaths: []string{ test.OfficeTestFilePath(t, "document.docx"),
test.OfficeTestFilePath(t, "document.docx"), })
}, require.Nil(t, err)
} req.SetPaperSize(A4)
req.SetLandscape(false)
dirPath, err := rand.Get() dirPath, err := rand.Get()
require.Nil(t, err) require.Nil(t, err)
dest := fmt.Sprintf("%s/foo.pdf", dirPath) dest := fmt.Sprintf("%s/foo.pdf", dirPath)