🐘 A PHP client for interacting with Gotenberg

Overview

Gotenberg PHP Logo

Gotenberg PHP

A PHP client for interacting with Gotenberg

Latest Version Total Downloads Continuous Integration https://codecov.io/gh/gotenberg/gotenberg


This package is a PHP client for Gotenberg, a developer-friendly API to interact with powerful tools like Chromium and LibreOffice to convert many documents (HTML, Markdown, Word, Excel, etc.) to PDF, transform them, merge them, and more!

⚠️ For Gotenberg 6.x, use thecodingmachine/gotenberg-php-client instead.

Quick Examples

You may convert a target URL to PDF and save it to a given directory:

use Gotenberg\Gotenberg;

// Converts a target URL to PDF and saves it to a given directory.
$filename = Gotenberg::save(
    Gotenberg::chromium($apiUrl)->url('https://my.url'), 
    $pathToSavingDirectory
);

You may also convert Office documents and merge them:

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

// Converts Office documents to PDF and merges them.
$response = Gotenberg::send(
    Gotenberg::libreOffice($apiUrl)
        ->merge()
        ->convert(
            Stream::path($pathToDocx),
            Stream::path($pathToXlsx)
        )
);

Requirement

This packages requires Gotenberg, a Docker-powered stateless API for PDF files:

Installation

This package can be installed with Composer:

composer require gotenberg/gotenberg-php

We use PSR-7 HTTP message interfaces (i.e., RequestInterface and ResponseInterface) and the PSR-18 HTTP client interface (i.e., ClientInterface).

For the latter, you may need an adapter in order to use your favorite client library. Check the available adapters:

If you're not sure which adapter you should use, consider using the php-http/guzzle7-adapter:

composer require php-http/guzzle7-adapter

Usage

Send a request to the API

After having created the HTTP request (see below), you have two options:

  1. Get the response from the API and handle it according to your need.
  2. Save the resulting file to a given directory.

In the following examples, we assume the Gotenberg API is available at https://localhost:3000.

Get a response

You may use any HTTP client that is able to handle a PSR-7 RequestInterface to call the API:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium('http://localhost:3000')
    ->url('https://my.url');
    
$response = $client->sendRequest($request);

If you have a PSR-18 compatible HTTP client (see Installation), you may also use Gotenberg::send:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium('http://localhost:3000')
    ->url('https://my.url');

try {
    $response = Gotenberg::send($request);
    return $response;
} catch (GotenbergApiErroed $e) {
    // $e->getResponse();
}

This helper will parse the response and if it is not 2xx, it will throw an exception. That's especially useful if you wish to return the response directly to the browser.

You may also explicitly set the HTTP client:

use Gotenberg\Gotenberg;

$response = Gotenberg::send($request, $client);

Save the resulting file

If you have a PSR-18 compatible HTTP client (see Installation), you may use Gotenberg::save:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium('http://localhost:3000')
    ->url('https://my.url');
    
$filename = Gotenberg::save($request, '/path/to/saving/directory');

It returns the filename of the resulting file. By default, Gotenberg creates a UUID filename (i.e., 95cd9945-484f-4f89-8bdb-23dbdd0bdea9) with either a .zip or a .pdf file extension.

You may also explicitly set the HTTP client:

use Gotenberg\Gotenberg;

$response = Gotenberg::save($request, $pathToSavingDirectory, $client);

Filename

You may override the output filename with:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium('http://localhost:3000')
    ->outputFilename('my_file')
    ->url('https://my.url');

Gotenberg will automatically add the correct file extension.

Trace or request ID

By default, Gotenberg creates a UUID trace that identifies a request in its logs. You may override its value thanks to:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium('http://localhost:3000')
    ->trace('debug')
    ->url('https://my.url');

It will set the header Gotenberg-Trace with your value. You may also override the default header name:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium('http://localhost:3000')
    ->trace('debug', 'Request-Id')
    ->url('https://my.url');

Please note that it should be the same value as defined by the --api-trace-header Gotenberg's property.

The response from Gotenberg will also contain the trace header. In case of error, both the Gotenberg::send and Gotenberg::save methods throw a GotenbergApiErroed exception that provides the following method for retrieving the trace:

use Gotenberg\Exceptions\GotenbergApiErroed;
use Gotenberg\Gotenberg;

try {
    $response = Gotenberg::send(
        Gotenberg::chromium('http://localhost:3000')
            ->url('https://my.url')
    );
} catch (GotenbergApiErroed $e) {
    $trace = $e->getGotenbergTrace();
    // Or if you override the header name:
    $trace = $e->getGotenbergTrace('Request-Id');
}

Chromium

The Chromium module interacts with the Chromium browser to convert HTML documents to PDF.

Convert a target URL to PDF

See https://gotenberg.dev/docs/modules/chromium#url.

Converting a target URL to PDF is as simple as:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium($apiUrl)
    ->url('https://my.url');

By default, Gotenberg auto-detects the following assets: .woff2, .woff, .ttf, .css and .js.

It adds the corresponding HTML elements (i.e., link and script) inside the DOM of the target URL, using the alphabetical order according to the filenames.

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

$request = Gotenberg::chromium($apiUrl)
    ->assets(
        Stream::path('/path/to/my.css'),
        Stream::path('/path/to/my.js')
    )
    ->url('https://my.url');

You may override this behavior thanks to the $extraLinkTags and $extraScriptTags arguments:

use Gotenberg\Gotenberg;
use Gotenberg\Modules\ChromiumExtraLinkTag;
use Gotenberg\Modules\ChromiumExtraScriptTag;
use Gotenberg\Stream;

$request = Gotenberg::chromium($apiUrl)
    ->url(
        'https://my.url',
        [
            ChromiumExtraLinkTag::url('https://my.css'),
            ChromiumExtraLinkTag::stream(Stream::path('/path/to/my.css')),
        ],
        [
            ChromiumExtraScriptTag::url('https://my.js'),
            ChromiumExtraScriptTag::stream(Stream::path('/path/to/my.js')),
        ]
    );

Please note that Gotenberg will add the <link> and <script> elements based on the order of the arguments.

Convert an HTML document to PDF

See https://gotenberg.dev/docs/modules/chromium#html.

You may convert an HTML document with:

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

$request = Gotenberg::chromium($apiUrl)
    ->html(Stream::path('/path/to/file.html'));

Or with an HTML string:

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

$request = Gotenberg::chromium($apiUrl)
    ->html(Stream::string('my.html', $someHtml);

Please note that it automatically sets the filename to index.html, as required by Gotenberg, whatever the value you're using with the Stream class.

You may also send additional files, like images, fonts, stylesheets, and so on. The only requirement is that their paths in the HTML DOM are on the root level.

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

$request = Gotenberg::chromium($apiUrl)
    ->assets(
        Stream::path('/path/to/my.css'),
        Stream::path('/path/to/my.js')
    )
    ->html(Stream::path('/path/to/file.html'));

Convert one or more markdown files to PDF

See https://gotenberg.dev/docs/modules/chromium#markdown.

You may convert markdown files with:

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

$request = Gotenberg::chromium($apiUrl)
    ->markdown(
        Stream::path('/path/to/my_wrapper.html'),
        Stream::path('/path/to/file.md')
    );

The first argument is a Stream with HTML content, for instance:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>My PDF</title>
  </head>
  <body>
    {{ toHTML "file.md" }}
  </body>
</html>

Here, there is a Go template function toHTML. Gotenberg will use it to convert a markdown file's content to HTML.

Like the HTML conversion, you may also send additional files, like images, fonts, stylesheets, and so on. The only requirement is that their paths in the HTML DOM are on the root level.

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

$request = Gotenberg::chromium($apiUrl)
    ->assets(
        Stream::path('/path/to/my.css'),
        Stream::path('/path/to/my.js')
    )
    ->markdown(
        Stream::path('/path/to/file.html'),
        Stream::path('/path/to/my.md')
        Stream::path('/path/to/my2.md')
    );

Paper size

You may override the default paper size with:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium($apiUrl)
    ->paperSize($width, $height)
    ->url('https://my.url');

Examples of paper size (width x height, in inches):

  • Letter - 8.5 x 11 (default)
  • Legal - 8.5 x 14
  • Tabloid - 11 x 17
  • Ledger - 17 x 11
  • A0 - 33.1 x 46.8
  • A1 - 23.4 x 33.1
  • A2 - 16.54 x 23.4
  • A3 - 11.7 x 16.54
  • A4 - 8.27 x 11.7
  • A5 - 5.83 x 8.27
  • A6 - 4.13 x 5.83

Margins

You may override the default margins (i.e., 0.39, in inches):

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium($apiUrl)
    ->margins($top, $bottom, $left, $right)
    ->url('https://my.url');

Prefer CSS page size

You may force page size as defined by CSS:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium($apiUrl)
    ->preferCssPageSize()
    ->url('https://my.url');

Print the background graphics

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium($apiUrl)
    ->printBackground()
    ->url('https://my.url');

Landscape orientation

You may override the default portrait orientation with:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium($apiUrl)
    ->landscape()
    ->url('https://my.url');

Scale

You may override the default scale of the page rendering (i.e., 1.0) with:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium($apiUrl)
    ->scale(2.0)
    ->url('https://my.url');

Page ranges

You may set the page ranges to print, e.g., 1-5, 8, 11-13. Empty means all pages.

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium($apiUrl)
    ->nativePageRanges('1-2')
    ->url('https://my.url');

Header and footer

You may add a header and/or a footer to each page of the PDF:

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

$request = Gotenberg::chromium($apiUrl)
    ->header(Stream::path('/path/to/my_header.html'))
    ->footer(Stream::path('/path/to/my_footer.html'))
    ->margins(1, 1, 0.39, 0.39)
    ->url('https://my.url');

Please note that it automatically sets the filenames to header.html and footer.html, as required by Gotenberg, whatever the value you're using with the Stream class.

Each of them has to be a complete HTML document:

<html>
<head>
    <style>
    body {
        font-size: 8rem;
        margin: 4rem auto;
    }
    </style>
</head>
<body>
<p><span class="pageNumber"></span> of <span class="totalPages"></span></p>
</body>
</html>

The following classes allow you to inject printing values:

  • date - formatted print date.
  • title - document title.
  • url - document location.
  • pageNumber - current page number.
  • totalPages - total pages in the document.

⚠️ Make sure that:

  1. Margins top and bottom are large enough (i.e., ->margins(1, 1, 0.39, 0.39))
  2. The font size is big enough.

⚠️ There are some limitations:

  • No JavaScript.
  • The CSS properties are independent of the ones from the HTML document.
  • The footer CSS properties override the ones from the header;
  • Only fonts installed in the Docker image are loaded - see the Fonts chapter.
  • Images only work using a base64 encoded source - i.e., data:image/png;base64, iVBORw0K....
  • background-color and color CSS properties require an additional -webkit-print-color-adjust: exact CSS property in order to work.
  • Assets are not loaded (i.e., CSS files, scripts, fonts, etc.).

Wait delay

When the page relies on JavaScript for rendering, and you don't have access to the page's code, you may want to wait a certain amount of time (i.e., 1s, 2ms, etc.) to make sure Chromium has fully rendered the page you're trying to generate.

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium($apiUrl)
    ->waitDelay('3s')
    ->url('https://my.url');

Wait for expression

You may also wait until a given JavaScript expression returns true:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium($apiUrl)
    ->waitForExpression("window.status === 'ready'")
    ->url('https://my.url');

User agent

You may override the default User-Agent header used by Gotenberg:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium($apiUrl)
    ->userAgent("Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1")
    ->url('https://my.url');

Extra HTTP headers

You may add HTTP headers that Chromium will send when loading the HTML document:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium($apiUrl)
    ->extraHttpHeaders([
        'My-Header-1' => 'My value',
        'My-Header-2' => 'My value'
    ])
    ->url('https://my.url');

Fail on console exceptions

You may force Gotenberg to return a 409 Conflict response if there are exceptions in the Chromium console:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium($apiUrl)
    ->failOnConsoleExceptions()
    ->url('https://my.url');

Emulate media type

Some websites have dedicated CSS rules for print. Using screen allows you to force the "standard" CSS rules:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium($apiUrl)
    ->emulateScreenMediaType()
    ->url('https://my.url');

You may also force the print media type with:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium($apiUrl)
    ->emulatePrintMediaType()
    ->url('https://my.url');

PDF Format

See https://gotenberg.dev/docs/modules/pdf-engines#engines.

You may set the PDF format of the resulting PDF with:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium($apiUrl)
    ->pdfFormat('PDF/A-1a')
    ->url('https://my.url');

LibreOffice

The LibreOffice module interacts with LibreOffice to convert documents to PDF, thanks to unoconv.

Convert documents to PDF

See https://gotenberg.dev/docs/modules/libreoffice#route.

Converting a document to PDF is as simple as:

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

$request = Gotenberg::libreOffice($apiUrl)
    ->convert(Stream::path('/path/to/my.docx'));

If you send many documents, Gotenberg will return a ZIP archive with the PDFs:

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

$request = Gotenberg::libreOffice($apiUrl)
    ->outputFilename('archive')
    ->convert(
        Stream::path('/path/to/my.docx'),
        Stream::path('/path/to/my.xlsx')
    );

// $filename = archive.zip
$filename = Gotenberg::save($request, $pathToSavingDirectory);

You may also merge them into one unique PDF:

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

$request = Gotenberg::libreOffice($apiUrl)
    ->merge()
    ->outputFilename('merged')
    ->convert(
        Stream::path('/path/to/my.docx'),
        Stream::path('/path/to/my.xlsx')
    );

// $filename = merged.pdf
$filename = Gotenberg::save($request, $pathToSavingDirectory);

Please note that the merging order is determined by the order of the arguments.

Landscape orientation

You may override the default portrait orientation with:

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

$request = Gotenberg::libreOffice($apiUrl)
    ->landscape()
    ->convert(Stream::path('/path/to/my.docx'));

Page ranges

You may set the page ranges to print, e.g., 1-4. Empty means all pages.

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

$request = Gotenberg::libreOffice($apiUrl)
    ->nativePageRanges('1-2')
    ->convert(Stream::path('/path/to/my.docx'));

⚠️ The page ranges are applied to all files independently.

PDF format

See https://gotenberg.dev/docs/modules/pdf-engines#engines.

You may set the PDF format of the resulting PDF(s) with:

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

$request = Gotenberg::libreOffice($apiUrl)
    ->pdfFormat('PDF/A-1a')
    ->convert(Stream::path('/path/to/my.docx'));

You may also explicitly tell Gotenberg to use unoconv to convert the resulting PDF(s) to the PDF/A-1a format:

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

$request = Gotenberg::libreOffice($apiUrl)
    ->nativePdfA1aFormat()
    ->convert(Stream::path('/path/to/my.docx'));

⚠️ You cannot set both property, otherwise Gotenberg will return 400 Bad Request response.

PDF Engines

The PDF Engines module gathers all engines that can manipulate PDF files.

Merge PDFs

See https://gotenberg.dev/docs/modules/pdf-engines#merge.

Merging PDFs is as simple as:

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

$request = Gotenberg::pdfEngines($apiUrl)
    ->merge(
        Stream::path('/path/to/my.pdf'),
        Stream::path('/path/to/my2.pdf')
    );

Please note that the merging order is determined by the order of the arguments.

You may also set the PDF format of the resulting PDF(s) with:

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

$request = Gotenberg::pdfEngines($apiUrl)
    ->pdfFormat('PDF/A-1a')
    ->merge(
        Stream::path('/path/to/my.pdf'),
        Stream::path('/path/to/my2.pdf'),
        Stream::path('/path/to/my3.pdf')
    );

Convert to a specific PDF format

See https://gotenberg.dev/docs/modules/pdf-engines#convert.

You may convert a PDF to a specific PDF format with:

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

$request = Gotenberg::pdfEngines($apiUrl)
    ->convert(
        'PDF/A-1a'
        Stream::path('/path/to/my.pdf')
    );

If you send many PDFs, Gotenberg will return a ZIP archive with the PDFs:

use Gotenberg\Gotenberg;
use Gotenberg\Stream;

$request = Gotenberg::pdfEngines($apiUrl)
    ->outputFilename('archive')
    ->convert(
        'PDF/A-1a',
        Stream::path('/path/to/my.pdf'),
        Stream::path('/path/to/my2.pdf'),
        Stream::path('/path/to/my3.pdf')
    );

// $filename = archive.zip
$filename = Gotenberg::save($request, $pathToSavingDirectory);

Webhook

The Webhook module is a Gotenberg middleware that sends the API responses to callbacks.

⚠️ You cannot use the Gotenberg::save method if you're using the webhook feature.

For instance:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium($apiUrl)
    ->webhook('https://my.webhook.url', 'https://my.webhook.error.url')
    ->url('https://my.url'); 

You may also override the default HTTP method (POST) that Gotenberg will use to call the webhooks:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium($apiUrl)
    ->webhook('https://my.webhook.url', 'https://my.webhook.error.url')
    ->webhookMethod('PATCH')
    ->webhookErrorMethod('PUT')
    ->url('https://my.url');

You may also tell Gotenberg to add extra HTTP headers that it will send alongside the request to the webhooks:

use Gotenberg\Gotenberg;

$request = Gotenberg::chromium($apiUrl)
    ->webhook('https://my.webhook.url', 'https://my.webhook.error.url')
    ->webhookExtraHttpHeaders([
        'My-Header-1' => 'My value',
        'My-Header-2' => 'My value'    
    ])
    ->url('https://my.url');
Comments
  • Laravel 8

    Laravel 8

    Does it works with Laravel 8?

    I tried to install and use it, but I got the error below:

    TypeError
    Symfony\Component\HttpFoundation\Response::setContent(): Argument #1 ($content) must be of type ?string, Nyholm\Psr7\Request given, called in ../vendor/laravel/framework/src/Illuminate/Http/Response.php on line 72 
    
    help wanted wontfix 
    opened by ramonMontanhes 11
  •  unexpected 'array' (T_ARRAY), expecting function (T_FUNCTION) or const (T_CONST) in MultipartFormDataModule.php on line 20

    unexpected 'array' (T_ARRAY), expecting function (T_FUNCTION) or const (T_CONST) in MultipartFormDataModule.php on line 20

    Hi,

    I've tried to convert an HTML page into a PDF but I already got the same error:

    "unexpected 'array' (T_ARRAY), expecting function (T_FUNCTION) or const (T_CONST) in MultipartFormDataModule.php on line 20"

    and i don't understand why.

    Here is my PHP code:

      <?php
        require 'vendor/autoload.php';
        use Gotenberg\Gotenberg;
        use Gotenberg\Stream;
        $apiUrl = "http://localhost:3000";
        $request = Gotenberg::chromium($apiUrl)->html(Stream::path('etiquette.html'));
        ?>
    

    I've tried with other method as:

    use Gotenberg\Gotenberg;
    
       // Converts a target URL to PDF and saves it to a given directory.
        $filename = Gotenberg::save(
        Gotenberg::chromium($apiUrl)->url('https://my.url'), 
        $pathToSavingDirectory
    );
    

    but I've got the same result.

    Have you got any idea about why I've got this error please?

    Thanks

    opened by Paul-Lebranchu 4
  • Error when passing associative array to merge function

    Error when passing associative array to merge function

    I'm getting an error when trying to pass an associative array to the merge call.

    There are actually two errors I'm getting, the first happens when trying to pass it like normal with argument unpacking:

       $streams = array_map(
            fn($long_url) => Stream::path($long_url),
            $keyed_array_of_urls
        );
    
        $request = Gotenberg::pdfEngines($apiUrl)
            ->outputFilename('requested-name')
            ->merge(
                ...$streams
            );
    

    The error I get is: Too few arguments to function Gotenberg\Modules\PdfEngines::merge(), 0 passed

    So to remedy that and match the function signature, I use array_shift() to match:

        $request = Gotenberg::pdfEngines($apiUrl)
            ->outputFilename('requested-name')
            ->merge(
                array_shift$streams),
                array_shift$streams),
                ...$streams
            );
    

    This gives me the error message: Unsupported operand types: string + int from vendor/gotenberg/gotenberg-php/src/Modules/PdfEngines.php:41

    I'm currently getting around this by simply using array_values() and not passing an associative array.

        $request = Gotenberg::pdfEngines($apiUrl)
            ->outputFilename('requested-name')
            ->merge(
                ...array_values($streams)
            );
    

    Just thought it might be worth bringing to your attention. Thanks for all the hard work!

    bug 
    opened by thaisonle 4
  • How to handle large file conversion (4gb)

    How to handle large file conversion (4gb)

    Hello,

    Thanks for the wonderful library. How to handle large file conversion? I can see you have already used stream but i still get internal 500 error.

    Any suggestions?

    opened by ssatz 2
  • How to loop to merge pdf

    How to loop to merge pdf

    Sorry for a newbies question,

    I want to merge pdf with pdfengine merge I have a loop for that based on the number of document to get.

    I think to use this function :

    use Gotenberg\Gotenberg;
    use Gotenberg\Stream;
    
    $request = Gotenberg::pdfEngines($apiUrl)
        ->merge(
            Stream::path('/path/to/my.pdf'),
            Stream::path('/path/to/my2.pdf')
        );
    

    How can I loop to add Stream::path ?

    Thanks for your feedback.

    Best regards

    opened by olopost 1
  • How to find out that the content will not fit on one page?

    How to find out that the content will not fit on one page?

    Hi, how do I know that the content of an html page will not fit on one pdf page and several pages will be created in the document? To make a document content page. Thanks)

    opened by AndreyZakhvatoshin 1
  • Wrong merge order if > 10 files

    Wrong merge order if > 10 files

    Hello @gulien ! I want to merge pdf files like this: $files = []; foreach ($this->pdf_pages as $name) { $files[] = Stream::path(Storage::path($this->dirPath . '/tmp/' . $name)); }

        $request = Gotenberg::pdfEngines('http://gotenberg:3000')
            ->outputFilename($resultFileName)
            ->merge(...$files);
    

    But the order is confused when file count > 10

    Originally posted by @AndreyZakhvatoshin in https://github.com/gotenberg/gotenberg/discussions/411#discussioncomment-2460897

    bug 
    opened by gulien 1
  • Merge of long urls pointing to PDFs failing

    Merge of long urls pointing to PDFs failing

    I have a situation where I have files sitting in an S3/GCS bucket and need to merge certain files from that bucket. Since cloud storage isn't treated the same as local storage by gotenberg, we use temporary URLs from the bucket to merge certain files together. These temporary URLs are very long (sometimes 400+ characters) and this seems to cause an error with the gotenberg API.

        $streams = collect($long_urls)->map(
            fn($long_url) => Stream::path($long_url)
        );
    
        $request = Gotenberg::pdfEngines($apiUrl)
            ->outputFilename('requested-name')
            ->merge(
                ...$streams
            );
    

    When I run this code with the long urls, I get a Gotenberg\Exceptions\GotenbergApiErroed error and if I check the gotenberg docker container, it says

    {
       "level":"error",
       "ts":1641567947.0926168,
       "logger":"api",
       "msg":"create request context: copy to disk: create local file: open /tmp/aabf345b-68eb-457a-bbcb-728cc3813e1f/0_2021%20AR%20Help%20Manual%2010-27-2021.pdf?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAQPF2CX2ONHXT3XG3%2F20220107%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20220107T150546Z&X-Amz-SignedHeaders=host&X-Amz-Expires=300&X-Amz-Signature=75620efd0a5e1c3520c398d50ea51c434b200e9785d830ddc350c14dbe714b4a: file name too long",
       "trace":"2aa4913a-534a-41af-911b-90296e43adc7",
       "remote_ip":"172.18.0.8",
       "host":"gotenberg:3000",
       "uri":"/forms/pdfengines/merge",
       "method":"POST",
       "path":"/forms/pdfengines/merge",
       "referer":"",
       "user_agent":"Symfony HttpClient/Curl",
       "status":500,
       "latency":5535083,
       "latency_human":"5.535083ms",
       "bytes_in":3083724,
       "bytes_out":21
    }
    

    I'm not sure if this is because of code changes between gotenberg/gotenberg 6 => 7 or from thecodingmachine/gotenberg => gotenberg/gotenberg-php but was wondering if I could get some help.

    opened by thaisonle 1
  • Disable Footer entirely rather than show the temporary filename?

    Disable Footer entirely rather than show the temporary filename?

    If there is an empty footer or header I would expect it to be empty. What is happening here?

    To resolve issues like https://github.com/puppeteer/puppeteer/issues/2089 we need to generate separate PDF:s and then merge. Some pages should not have footer or header, while others should.

            $this->gotenbergChromium = Gotenberg::chromium($this->baseUri)
                // No margins, but many pages will define using @page css rules
                ->margins(0, 0, 0, 0)
                // A4 in inches
                ->paperSize(8.275, 11.7)
                ->preferCssPageSize()
                ->printBackground();
    

    Then later:

            foreach ($documents as $document) {
                if ($document->showFooter()) {
                    $this->gotenbergChromium->footer(
                        Stream::string('footer.html', $document->renderFooterHtml())
                    );
                } else {
                    $this->gotenbergChromium->footer(
                        Stream::string('footer.html', '')
                    );
                }
    
                // Add main content
                // Save PDF content
                // Merge multiple pages
            }
    

    Result: image

    opened by NiklasBr 7
  • "context deadline exceeded" with consecutive requests

      gotenberg:
          image: gotenberg/gotenberg:7.7
          ports:
              - "3000:3000"
          command: [
              gotenberg,
              --chromium-ignore-certificate-errors=true,
              --chromium-disable-web-security,
              --uno-listener-restart-threshold=0
          ]
    

    With the following code:

    $partialDocuments = [];
    foreach ($document->getAllChildren() as $child) {
        $html = $document->renderDocument($params);
        $request = Gotenberg::chromium($this->baseUri)->html(
            Stream::string($child->getPdfFileName() . '--transient.html', $html)
        );
        $partialDocuments[] = Gotenberg::save($request, SYSTEM_TEMP_DIRECTORY . DIRECTORY_SEPARATOR);
        sleep(2);
    }
    

    Next step is to merge the separate PDF:s but cannot reach it because the third $child crashes Gotenberg.

    2022-11-18 15:00:31 {"level":"info","ts":1668780031.5957,"logger":"api","msg":"request handled","trace":"2f01838c-53b2-4d19-a0ad-b005cd94b324","remote_ip":"172.18.0.10","host":"gotenberg:3000","uri":"/forms/chromium/convert/html","method":"POST","path":"/forms/chromium/convert/html","referer":"","user_agent":"Symfony HttpClient/Curl","status":200,"latency":2557421751,"latency_human":"2.557421751s","bytes_in":4011,"bytes_out":18070}
    2022-11-18 15:00:47 {"level":"info","ts":1668780047.2433655,"logger":"api","msg":"request handled","trace":"4e0f0f1c-f587-4756-ae79-eccc3da6b5bb","remote_ip":"172.18.0.10","host":"gotenberg:3000","uri":"/forms/chromium/convert/html","method":"POST","path":"/forms/chromium/convert/html","referer":"","user_agent":"Symfony HttpClient/Curl","status":200,"latency":2398633335,"latency_human":"2.398633335s","bytes_in":8009,"bytes_out":18448}
    2022-11-18 15:01:28 {"level":"error","ts":1668780088.1366816,"logger":"api","msg":"convert HTML to PDF: convert to PDF: chromium PDF: wait for events: wait for event networkIdle: context deadline exceeded","trace":"bf54e5fc-ad6b-4f28-b8ca-f6f41f2e3386","remote_ip":"172.18.0.10","host":"gotenberg:3000","uri":"/forms/chromium/convert/html","method":"POST","path":"/forms/chromium/convert/html","referer":"","user_agent":"Symfony HttpClient/Curl","status":503,"latency":30012295722,"latency_human":"30.012295722s","bytes_in":11648,"bytes_out":19}
    

    The PHP exception is:

    "Gotenberg\Exceptions\GotenbergApiErroed: Service Unavailable in vendor/gotenberg/gotenberg-php/src/Exceptions/GotenbergApiErroed.php:16
    Stack trace:
    #0 vendor/gotenberg/gotenberg-php/src/Gotenberg.php(55): Gotenberg\Exceptions\GotenbergApiErroed::createFromResponse(Object(GuzzleHttp\Psr7\Response))
    #1 vendor/gotenberg/gotenberg-php/src/Gotenberg.php(71): Gotenberg\Gotenberg::send(Object(GuzzleHttp\Psr7\Request), Object(Symfony\Component\HttpClient\Psr18Client))
    #2 GotenbergPhp.php(182): Gotenberg\Gotenberg::save(Object(GuzzleHttp\Psr7\Request), '/var/www/...')
    #3 GotenbergPhp->buildPdf(Object(\Document\Printpage), Object(stdClass))
    #4 Processor.php(130): Web2Print\Processor\GotenbergPhp->buildPdf(Object("
    
    opened by NiklasBr 2
  • feat(chromium): make the paper size unit configurable

    feat(chromium): make the paper size unit configurable

    On Chromium, we can currently only provide the page size in inches. I'm sure there are technical reasons behind this, but it forces users to make a conversion if they are not used to imperial units.

    To make it possible to use other units, I propose to:

    • add a $unitFactor that takes a multiplier for conversion (by default, it is 1 to keep inches)
    • add three constants for the most used multipliers for paper sizes (inches, centimeters, millimeters).

    This approach has the advantages to keep one method to set the page size, and to allow users to provide any other multipliers they want, so they can set a size in feet or in meters, for instance.

    opened by Deuchnord 2
Releases(v1.1.1)
  • v1.1.1(Dec 9, 2022)

  • v1.1.0(Oct 21, 2022)

  • v1.0.1(Mar 29, 2022)

  • v1.0.0(Feb 8, 2022)

    First stable release, with new features from Gotenberg 7.5.0.

    Please note there are small breaking changes compared to v0.1.4 regarding the ChromiumExtraLinkTag and ChromiumExtraScriptTag classes:

    • ~~ChromiumExtraLinkTag::url($myUrl)~~ and ~~ChromiumExtraLinkTag::stream($myStream)~~ => new ChromiumExtraLinkTag($href)
    • ~~ChromiumExtraScriptTag::url($myUrl)~~ and ~~ChromiumExtraScriptTag::stream($myStream)~~ => new ChromiumExtraScriptTag($src)
    Source code(tar.gz)
    Source code(zip)
  • v0.1.4(Jan 18, 2022)

  • v0.1.3(Jan 10, 2022)

  • v0.1.2(Dec 14, 2021)

  • v0.1.1(Dec 3, 2021)

    This new release fixes #1; Gotenberg::send and Gotenberg::save methods do not throw a GotenbergApiErroed exception anymore if the status code is in the 2xx range.

    The GotenbergApiErroed exception also provides a method to access the response, i.e., $e->getResponse().

    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(Nov 28, 2021)

Owner
Gotenberg
Gotenberg
PHP library generating PDF files from UTF-8 encoded HTML

mPDF is a PHP library which generates PDF files from UTF-8 encoded HTML. It is based on FPDF and HTML2FPDF (see CREDITS), with a number of enhancement

null 3.8k Jan 2, 2023
PHP library allowing thumbnail, snapshot or PDF generation from a url or a html page. Wrapper for wkhtmltopdf/wkhtmltoimage

Snappy Snappy is a PHP library allowing thumbnail, snapshot or PDF generation from a url or a html page. It uses the excellent webkit-based wkhtmltopd

KNP Labs 4.1k Dec 30, 2022
Official clone of PHP library to generate PDF documents and barcodes

TCPDF PHP PDF Library Please consider supporting this project by making a donation via PayPal category Library author Nicola Asuni [email protected] co

Tecnick.com LTD 3.6k Jan 6, 2023
TCPDF - PHP PDF Library - https://tcpdf.org

tc-lib-pdf PHP PDF Library UNDER DEVELOPMENT (NOT READY) UPDATE: CURRENTLY ALL THE DEPENDENCY LIBRARIES ARE ALMOST COMPLETE BUT THE CORE LIBRARY STILL

Tecnick.com LTD 1.3k Dec 30, 2022
A PHP report generator

PHPJasper A PHP Report Generator Docs About PHPJasper is the best solution to compile and process JasperReports (.jrxml & .jasper files) just using PH

PHPJasper 404 Dec 29, 2022
Pdf and graphic files generator library written in php

Information Examples Sample documents are in the "examples" directory. "index.php" file is the web interface to browse examples, "cli.php" is a consol

Piotr Śliwa 335 Nov 26, 2022
PdfParser, a standalone PHP library, provides various tools to extract data from a PDF file.

PdfParser Pdf Parser, a standalone PHP library, provides various tools to extract data from a PDF file. Website : https://www.pdfparser.org Test the A

Sebastien MALOT 1.9k Jan 2, 2023
A PHP tool that helps you write eBooks in markdown and convert to PDF.

Artwork by Eric L. Barnes and Caneco from Laravel News ❤️ . This PHP tool helps you write eBooks in markdown. Run ibis build and an eBook will be gene

Mohamed Said 1.6k Jan 2, 2023
Generate simple PDF invoices with PHP

InvoiScript Generate simple PDF invoices with PHP. Installation Run: composer require mzur/invoiscript Usage Example use Mzur\InvoiScript\Invoice; re

Martin Zurowietz 16 Aug 24, 2022
PHP library allowing PDF generation or snapshot from an URL or an HTML page. Wrapper for Kozea/WeasyPrint

PhpWeasyPrint PhpWeasyPrint is a PHP library allowing PDF generation from an URL or an HTML page. It's a wrapper for WeasyPrint, a smart solution help

Pontedilana 23 Oct 28, 2022
FPDI is a collection of PHP classes facilitating developers to read pages from existing PDF documents and use them as templates in FPDF.

FPDI - Free PDF Document Importer ❗ This document refers to FPDI 2. Version 1 is deprecated and development is discontinued. ❗ FPDI is a collection of

Setasign 821 Jan 4, 2023
A slim PHP wrapper around wkhtmltopdf with an easy to use and clean OOP interface

PHP WkHtmlToPdf PHP WkHtmlToPdf provides a simple and clean interface to ease PDF and image creation with wkhtmltopdf. The wkhtmltopdf and - optionall

Michael Härtl 1.5k Dec 25, 2022
Official clone of PHP library to generate PDF documents and barcodes

TCPDF PHP PDF Library Please consider supporting this project by making a donation via PayPal category Library author Nicola Asuni [email protected] co

Tecnick.com LTD 3.6k Dec 26, 2022
PHP library allowing thumbnail, snapshot or PDF generation from a url or a html page.

Snappy Snappy is a PHP library allowing thumbnail, snapshot or PDF generation from a url or a html page. It uses the excellent webkit-based wkhtmltopd

KNP Labs 4.1k Dec 30, 2022
PHP Wrapper for callas pdfToolbox

PHP Wrapper for callas pdfToolbox A PHP wrapper class for callas pdfToolbox. Installation This library is installed via Composer. To install, use comp

Alannah Kearney 0 Feb 5, 2022
Utility PHP class to simplify interacting with persistent dismissible WordPress notices, promos, and banners

Persistent Dismissible A class for encapsulating the logic required to maintain a relationship between the database, a dismissible UI element (with an

Sandhills Development, LLC 22 Oct 11, 2022
Official PHP SDK for interacting with the Knock API.

Knock PHP library Documentation See the documentation for PHP usage examples

Knock 4 Dec 16, 2022
PHP library for interacting with the Waves blockchain.

Waves-PHP PHP client library for interacting with Waves blockchain platform. Installation composer require waves/client Usage See example.php for full

Waves Protocol 4 Sep 30, 2022
GraphQL API for interacting with Gravity Forms.

?? ?? WPGraphQL for Gravity Forms A WordPress plugin that provides a GraphQL API for interacting with Gravity Forms. Join the WPGraphQL community on S

Harness Software 135 Jan 2, 2023
Interacting with Mastodon's REST API for Kirby v3

Kirby3 Mastodon This plugin provides access to your Mastodon statuses, called 'toots'. Getting started Use one of the following methods to install & u

Fundevogel 5 Dec 31, 2022