Skip to content

Commit

Permalink
Add gotenberg output filename
Browse files Browse the repository at this point in the history
  • Loading branch information
StevenRenaux committed Jan 8, 2025
1 parent 9a5c76a commit f247756
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 15 deletions.
5 changes: 3 additions & 2 deletions src/Builder/AsyncBuilderTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ public function generateAsync(): void
}

if (null !== $this->fileName) {
// Gotenberg will add the extension to the file name (e.g. filename : "file.pdf" => generated file : "file.pdf.pdf").
$headers['Gotenberg-Output-Filename'] = $this->fileName;
/** @var string $basename Gotenberg will add the extension to the file name */
$basename = preg_replace('/\.[^.]+$/', '', $this->fileName);
$headers['Gotenberg-Output-Filename'] = $basename;
}
$this->client->call($this->getEndpoint(), $this->getMultipartFormData(), $headers);
}
Expand Down
15 changes: 13 additions & 2 deletions src/Builder/DefaultBuilderTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Psr\Log\LoggerInterface;
use Sensiolabs\GotenbergBundle\Client\GotenbergClientInterface;
use Sensiolabs\GotenbergBundle\Exception\InvalidBuilderConfiguration;
use Sensiolabs\GotenbergBundle\Exception\JsonEncodingException;
use Sensiolabs\GotenbergBundle\Formatter\AssetBaseDirFormatter;
use Sensiolabs\GotenbergBundle\Processor\NullProcessor;
Expand Down Expand Up @@ -69,6 +70,10 @@ protected function encodeData(string $key, mixed $value): array
*/
public function fileName(string $fileName, string $headerDisposition = HeaderUtils::DISPOSITION_INLINE): static
{
if (!preg_match('/\.[^.]+$/', $fileName)) {
throw new InvalidBuilderConfiguration(\sprintf('File name "%s" needs to get extension as ".pdf", ".png" or any other valid extension.', $fileName));
}

$this->fileName = $fileName;
$this->headerDisposition = $headerDisposition;

Expand Down Expand Up @@ -216,11 +221,17 @@ public function generate(): GotenbergFileResult

$processor = $this->processor ?? new NullProcessor();

$headers = [];
if (null !== $this->fileName) {
/** @var string $basename Gotenberg will add the extension to the file name */
$basename = preg_replace('/\.[^.]+$/', '', $this->fileName);
$headers['Gotenberg-Output-Filename'] = $basename;
}

return new GotenbergFileResult(
$this->client->call($this->getEndpoint(), $this->getMultipartFormData()),
$this->client->call($this->getEndpoint(), $this->getMultipartFormData(), $headers),
$processor($this->fileName),
$this->headerDisposition,
$this->fileName,
);
}
}
13 changes: 9 additions & 4 deletions src/Builder/GotenbergFileResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Sensiolabs\GotenbergBundle\Builder;

use Sensiolabs\GotenbergBundle\Client\GotenbergResponse;
use Sensiolabs\GotenbergBundle\Exception\ClientException;
use Sensiolabs\GotenbergBundle\Exception\ProcessorException;
use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
Expand All @@ -18,7 +19,6 @@ public function __construct(
protected readonly GotenbergResponse $response,
protected readonly \Generator $processorGenerator,
protected readonly string $disposition,
protected readonly string|null $fileName = null,
) {
}

Expand Down Expand Up @@ -61,11 +61,16 @@ public function process(): mixed
public function stream(): StreamedResponse
{
$headers = $this->getHeaders();
$headers->set('X-Accel-Buffering', 'no'); // See https://symfony.com/doc/current/components/http_foundation.html#streaming-a-json-response
if (null !== $this->fileName) {
$headers->set('Content-Disposition', HeaderUtils::makeDisposition($this->disposition, $this->fileName));

if (!preg_match('/filename="([^"]+)"/', $headers->get('Content-Disposition', ''), $matches)) {
throw new ClientException('No Content-Disposition header returned by Gotenberg.');
}

$contentDisposition = HeaderUtils::makeDisposition($this->disposition, $matches[1]);

$headers->set('X-Accel-Buffering', 'no'); // See https://symfony.com/doc/current/components/http_foundation.html#streaming-a-json-response
$headers->set('Content-Disposition', $contentDisposition);

return new StreamedResponse(
function (): void {
if (!$this->response->getStream()->valid()) {
Expand Down
8 changes: 5 additions & 3 deletions tests/Builder/GotenbergFileResultTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ protected function setUp(): void
$this->response = new GotenbergResponse(
$client->stream($client->request('GET', '/')),
200,
new ResponseHeaderBag(),
new ResponseHeaderBag([
'Content-Disposition' => 'inline; filename="file.pdf"',
]),
);

$this->processorGenerator = (function () {
Expand All @@ -43,7 +45,7 @@ protected function setUp(): void
#[TestDox('Response is processed')]
public function testProcess(): void
{
$result = new GotenbergFileResult($this->response, $this->processorGenerator, 'inline', 'file.pdf');
$result = new GotenbergFileResult($this->response, $this->processorGenerator, 'inline');
$process = $result->process();

self::assertSame('abc', $process);
Expand All @@ -53,7 +55,7 @@ public function testProcess(): void
#[TestDox('Response is streamed')]
public function testStream(): void
{
$result = new GotenbergFileResult($this->response, $this->processorGenerator, 'inline', 'file.pdf');
$result = new GotenbergFileResult($this->response, $this->processorGenerator, 'inline');
$stream = $result->stream();

ob_start();
Expand Down
10 changes: 7 additions & 3 deletions tests/Builder/Pdf/AbstractPdfBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,20 @@ public function testFilenameIsCorrectlySetOnResponse(): void
{
// @phpstan-ignore-next-line
$this->gotenbergClient = new GotenbergClient(new MockHttpClient([
new MockResponse(),
new MockResponse(info: [
'response_headers' => [
'Content-Disposition' => 'attachment; filename="some_file.pdf"',
],
]),
]));

$response = $this->getPdfBuilder()
->fileName('some_file.png', HeaderUtils::DISPOSITION_ATTACHMENT)
->fileName('some_file.pdf', HeaderUtils::DISPOSITION_ATTACHMENT)
->generate()
->stream()
;

self::assertSame('attachment; filename=some_file.png', $response->headers->get('Content-Disposition'));
self::assertSame('attachment; filename=some_file.pdf', $response->headers->get('Content-Disposition'));
}

public static function nativeNormalizersProvider(): \Generator
Expand Down
6 changes: 5 additions & 1 deletion tests/Builder/Screenshot/AbstractScreenshotBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ public function testFilenameIsCorrectlySetOnResponse(): void
{
// @phpstan-ignore-next-line
$this->gotenbergClient = new GotenbergClient(new MockHttpClient([
new MockResponse(),
new MockResponse(info: [
'response_headers' => [
'Content-Disposition' => 'attachment; filename="some_file.png"',
],
]),
]));

$response = $this->getScreenshotBuilder()
Expand Down

0 comments on commit f247756

Please sign in to comment.