gotenberg / gotenberg-php Goto Github PK
View Code? Open in Web Editor NEW🐘 A PHP client for interacting with Gotenberg.
License: MIT License
🐘 A PHP client for interacting with Gotenberg.
License: MIT License
php:8.3.4
gotenberg:8.3.0
Executing the following code always returns:code=405, message=Method Not Allowed
$request = Gotenberg::libreOffice("http://gotenberg:3000") ->convert(Stream::path(BASE_PATH . '/storage/pdf/2023.docx')); Gotenberg::save($request, BASE_PATH . '/storage');
Docker logs
{"level":"error","ts":1712074302.3096998,"logger":"api","msg":"code=405, message=Method Not Allowed","trace":"86ea7b13-eeb4-4cb6-b208-b6eca9267db6","remote_ip":"172.19.0.3","host":"gotenberg:3000","uri":"/forms/libreoffice/convert","method":"PUT","path":"/forms/libreoffice/convert","referer":"","user_agent":"GuzzleHttp/7","status":405,"latency":58400,"latency_human":"58.4µs","bytes_in":0,"bytes_out":18}
Hi,
I can't figure out what I am do wrong when setting header and footer, or if this is a bug.
PHP is in version 8.2.12
Gotenberg docker version 8.3.0
If I do not set them, nothing in pdf file. --> ok
If I set them to ""
, default browser values. --> ok
$req->header(Stream::string($rootDir."header.html", ""));
$req->footer(Stream::string($rootDir."footer.html', ""));
If I set anything else, nothing appears.
$req = Gotenberg::chromium('http://gotenberg:3000')->pdf();
$req->outputFilename('test');
$req->header(Stream::string($rootDir.'header.html', '<html><head></head><body>HEADER</body></html>'));
$req->footer(Stream::string($rootDir.'footer.html', '<html><head></head><body>FOOTER</body></html>'));
$req = $req->html(Stream::string($rootDir.'html.html', '<html><head></head><body>CONTENT '.date('Y-m-d H:i:s').'</body></html>'));
$res = Gotenberg::save($req, $rootDir);
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?
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
^
This kind of problematic as the webhook feature returns a 204 No Content
response on success.
Hi,
The recent tag does not follow the semver structure like old tags. Plus the tag version jumped from 1.1 to 1.18
I'm having an issue on 8.2.0 (Maybe related to gotenberg/gotenberg#403?)
Using Laravel + Sail on WSL2
docker-compose.yml
gotenberg:
image: gotenberg/gotenberg:8
extra_hosts:
- 'host.docker.internal:host-gateway'
ports:
- '${FORWARD_GOTENBERG_PORT:-3000}:3000'
volumes:
- './public/fonts:/usr/local/share/fonts'
command:
- "gotenberg"
- "--log-level=debug"
networks:
- sail
ive made a static page at /sample which literally says just "Hello, World!"
from inside the gotenberg container curl http://laravel.test/sample
works fine
I can run the following from inside the laravel app container (not the gotenberg container)
curl \
--request POST http://gotenberg:3000/forms/chromium/convert/url \
--form url=http://laravel.test/sample \
-o my.pdf
it works fine, my.pdf appears in the project root. with the words "Hello, World!" on it.
But from the application when I run (gotenberg/gotenberg-php)
$request = Gotenberg::chromium(config('gotenberg.url'))
->pdf()
->failOnConsoleExceptions()
->outputFilename('my-custom-pdf')
->url('http://laravel.test:80/sample');
$response = Gotenberg::send($request);
return $response
->withHeader('Content-Type', 'application/pdf')
->withHeader('Content-Disposition', 'inline; filename="generated.pdf"');
I keep getting:
ypa-filament-app-gotenberg-1 | {"level":"error","ts":1709274087.9005635,"logger":"api","msg":"convert URL to PDF: conv
ert to PDF: context deadline exceeded","trace":"efa04a81-fb5a-4cfe-abb3-80e0d6e81a00","remote_ip":"172.23.0.8","host":"
gotenberg:3000","uri":"/forms/chromium/convert/url","method":"POST","path":"/forms/chromium/convert/url","referer":"","
user_agent":"GuzzleHttp/7","status":503,"latency":30000270232,"latency_human":"30.000270232s","bytes_in":316,"bytes_out":19}
P.S. if i call ->html(Stream::string('sample', view('sample')->render()))
though it does work. its only url()
thats the problem. But if I have any images in the view the same timeout happens. The image urls also are something like 'http://localhost/img/example.jpg' and I don't think the Gotenberg container can resolve localhost so I'm not even sure what the correct implementation is.
Been fighting this all day. Please help 🙏
What I need is an endpoint that does the same as the "merge" endpoint (not do any converting / "touching" the raw data) and just accept the stream and create a PDF, but then, for a single PDF.
What I have done atm is "hack" the php-client and added a "render" method which removes the second and third argument (Stream $pdf2, Stream ...$pdfs) and just set the data for a single PDF and send it to the "merge" endpoint, and this works perfectly. But this feels very incorrect.
I'm just not fluent enough in Go to open a PR and help you guys with the Go side of things.
I wouldn't mind opening a PR to the php-client side though and maybe even make it more extensible (atm I had to copy the entire class because of concrete types and private properties in stead of interfaces and protected properties (e.g.)).
How can we upload merged file to S3 without storing it to local storage.
Here is my code.
`$array=[Stream::path($file_name),Stream::path($file_name),Stream::path($file_name)];
$request = Gotenberg::libreOffice("https://demo.gotenberg.dev")
->outputFilename('merged')
->merge()
->convert(...$array)`
Greetings!
I am sorry to pollute your ticket stream with a support request. 😞
✅ I have successfully implemented the gotenberg (v7) docker image and this library into my Symfony-based project.
✅ I have successfully "merged" its use with FlySystem via the OneupFlysystemBundle
✅ I am successfully producing merged pdfs from sources of html & office docs and storing them to AWS/S3 via the AwsS3 Flysystem adapter!
So all, in all, I am quite happy with the end product. I have one kludgy bit however, which I wondered if you might assist me.
Flysystem works well with Streams. But not directly with your Stream class. Therefore I end up doing something like this several times in my project:
use Gotenberg\Stream;
use GuzzleHttp\Psr7\Stream as Psr7Stream;
....
$streams = [];
foreach ($mountPaths as $mountPath) {
$psr7Stream = new Psr7Stream($this->mountManager->readStream($mountPath));
$streams[] = new Stream('file.pdf', $psr7Stream);
}
$request = $this->gotenberg->pdfEngines()
->outputFilename($destination)
->merge(...$streams);
(my gotenberg
instance above is simply a wrapper of yours in order to include other services with DI)
You can see the gymnastics I am doing to first create the Psr7Stream (readStream
returns a resource
), then secondly create an instead of Stream
.
Is there a cleaner way to do this? Can I create a Gotenberg/Stream
directly from a resource or handle this differently?
Secondly, I'd like to write a stream directly from the response. Currently I do this:
$response = $this->send($request, $client);
...
$this->mountManager->write($mountPath.$filename, $response->getBody()->getContents());
I'd prefer to use Flysystem's writeStream
method here if possible, Is it possible to get a Stream from the response?
As I said, I apologize in advance for the support request. I'm sure you're rolling your eyes at my stupidity 🙄 🤣 . Thanks in advance! 🙇
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)
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
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.
If I add a header and/or footer to each page of the PDF, the main content between header and footer is missing
when using the string() method of Stream class:
->html(Stream::string('index.html', $html));
If I use the path() method of the Stream class instead, it works:
->html(Stream::path('/var/www/html/public/test.html'));
When I comment out header() and footer() chained methods,
->html(Stream::string('index.html', $html));
is also working.
Is this a bug or am I missing something?
This is my test script:
<?php
use Gotenberg\Gotenberg;
use Gotenberg\Stream;
require_once "vendor/autoload.php";
//$html = file_get_contents('/var/www/html/public/test.html');
$chromium = Gotenberg::chromium('http://gotenberg:3000')
//->pdf() // uncomment for gotenberg/gotenberg-php ^2.0; Same results on version 2.0.0
->header(Stream::path('http://nginx:80/header/de'))
->footer(Stream::path('http://nginx:80/footer/de'))
// With this, main content will not be printed to PDF if header() and/or footer() are also chained;
// If header() and footer() are commented out, main content is printed correctly to PDF
//->html(Stream::string('index.html', $html));
// with this, main content is ALWAYS printed correctly to PDF
->html(Stream::path('/var/www/html/public/test.html'));
$response = Gotenberg::send($chromium);
file_put_contents('/var/www/html/public/test.pdf', $response->getBody()->getContents());
echo "done.\n";
Hi,
I'm trying to print blade view using url, Stream
Url :
$request = Gotenberg::chromium('http://gotenberg:3000')
->pdf()
->skipNetworkIdleEvent()
->url(url('template4'));
I get a blank pdf page, while if I use other url like google.com, it works fine.
NB: I can access to url('template4')
.
Stream :
$inv = view('print.sales.templates.4.main')->render();
$request = Gotenberg::chromium('http://gotenberg:3000')
->pdf()
->html(Stream::string('my.html', $inv));
It works but without CSS !! (I'm using boostrap css)
What am I missing ?
I'm not sure but it failed:
Gotenberg::libreOffice('http://localhost:3000')
->convert('Some remote file on s3.pdf');
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
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!
refs #9
your Index class produces something like
A B C D E F ... AA AB AC ...
except when sorting, AB
comes before B
, so it is sorted wrongly.
I recommend deleting your Index class and using something like this (untested):
public function merge(Stream $pdf1, Stream $pdf2, Stream ...$pdfs): RequestInterface
{
foreach ([$pdf1, $pdf2, ...$pdfs] as $pdf) {
$this->formFile(hrtime(true) . '_' . $pdf->getFilename(), $pdf->getStream());
}
$this->endpoint = '/forms/pdfengines/merge';
return $this->request();
}
If there is an empty footer or header I would expect it to be empty. What is happening here?
To resolve issues like puppeteer/puppeteer#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
}
My Php code
$request = Gotenberg::chromium('http://127.0.0.1:3000') ->url("http://host.docker.internal:8000/invoice/view");
$response = Gotenberg::send($request);
OS is ubuntu 22.
Docker container was started using docker run --rm --add-host host.docker.internal:host-gateway -p 3000:3000 gotenberg/gotenberg:7
Was able to successfully curl from within the docker instance by following the commands
docker exec -it <hash> bash; curl "http://host.docker.internal:8001/invoice/view"
Docker logs
"
{"level":"error","ts":1704128572.4625182,"logger":"api","msg":"convert URL to PDF: convert to PDF: context deadline exceeded","trace":"ba64d68d-0eb2-4834-831a-8db4d8415904","remote_ip":"172.17.0.1","host":"127.0.0.1:3000","uri":"/forms/chromium/convert/url","method":"POST","path":"/forms/chromium/convert/url","referer":"","user_agent":"GuzzleHttp/7","status":503,"latency":30001594641,"latency_human":"30.001594641s","bytes_in":203,"bytes_out":19}
"
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 gotenberg/gotenberg#411 (reply in thread)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.