Exports: Improved PDF command temp file cleanup

This commit is contained in:
Dan Brown 2025-01-01 15:19:11 +00:00
parent 6d7ff59a89
commit 7e31725d48
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
2 changed files with 28 additions and 2 deletions

View File

@ -90,18 +90,28 @@ class PdfGenerator
$process = Process::fromShellCommandline($command);
$process->setTimeout($timeout);
$cleanup = function () use ($inputHtml, $outputPdf) {
foreach ([$inputHtml, $outputPdf] as $file) {
if (file_exists($file)) {
unlink($file);
}
}
};
try {
$process->run();
} catch (ProcessTimedOutException $e) {
$cleanup();
throw new PdfExportException("PDF Export via command failed due to timeout at {$timeout} second(s)");
}
if (!$process->isSuccessful()) {
$cleanup();
throw new PdfExportException("PDF Export via command failed with exit code {$process->getExitCode()}, stdout: {$process->getOutput()}, stderr: {$process->getErrorOutput()}");
}
$pdfContents = file_get_contents($outputPdf);
unlink($outputPdf);
$cleanup();
if ($pdfContents === false) {
throw new PdfExportException("PDF Export via command failed, unable to read PDF output file");

View File

@ -5,6 +5,7 @@ namespace Tests\Exports;
use BookStack\Entities\Models\Page;
use BookStack\Exceptions\PdfExportException;
use BookStack\Exports\PdfGenerator;
use FilesystemIterator;
use Tests\TestCase;
class PdfExportTest extends TestCase
@ -128,7 +129,7 @@ class PdfExportTest extends TestCase
}, PdfExportException::class);
}
public function test_pdf_command_timout_option_limits_export_time()
public function test_pdf_command_timeout_option_limits_export_time()
{
$page = $this->entities->page();
$command = 'php -r \'sleep(4);\'';
@ -143,4 +144,19 @@ class PdfExportTest extends TestCase
}, PdfExportException::class,
"PDF Export via command failed due to timeout at 1 second(s)");
}
public function test_pdf_command_option_does_not_leave_temp_files()
{
$tempDir = sys_get_temp_dir();
$startTempFileCount = iterator_count((new FileSystemIterator($tempDir, FilesystemIterator::SKIP_DOTS)));
$page = $this->entities->page();
$command = 'cp {input_html_path} {output_pdf_path}';
config()->set('exports.pdf_command', $command);
$this->asEditor()->get($page->getUrl('/export/pdf'));
$afterTempFileCount = iterator_count((new FileSystemIterator($tempDir, FilesystemIterator::SKIP_DOTS)));
$this->assertEquals($startTempFileCount, $afterTempFileCount);
}
}