Skip to content

Commit b9b0ec7

Browse files
authored
fix: cleanup on finished stream (#1790)
1 parent d7685f9 commit b9b0ec7

4 files changed

Lines changed: 691 additions & 25 deletions

File tree

src/Export/Service/DownloadService.php

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use Pimcore\Bundle\StudioBackendBundle\Util\Constant\HttpResponseHeaders;
2626
use Pimcore\Bundle\StudioBackendBundle\Util\Trait\StreamedResponseTrait;
2727
use Pimcore\Bundle\StudioBackendBundle\Util\Trait\TempFilePathTrait;
28+
use Psr\Log\LoggerInterface;
2829
use Symfony\Component\HttpFoundation\Response;
2930
use Symfony\Component\HttpFoundation\StreamedResponse;
3031
use function sprintf;
@@ -39,7 +40,8 @@
3940

4041
public function __construct(
4142
private ExecutionEngineServiceInterface $executionEngineService,
42-
private StorageServiceInterface $storageService
43+
private LoggerInterface $logger,
44+
private StorageServiceInterface $storageService,
4345
) {
4446
}
4547

@@ -59,27 +61,27 @@ public function downloadResourceByJobRunId(
5961
$filePath = $folderName . '/' . $fileName;
6062
$storage = $this->validateStorage($filePath, $jobRunId);
6163

62-
$streamedResponse = $this->getFileStreamedResponse(
63-
$filePath,
64-
$mimeType,
65-
$downloadName,
66-
$storage
64+
return $this->getFileStreamedResponse(
65+
path: $filePath,
66+
mimeType: $mimeType,
67+
filename: $downloadName,
68+
storage: $storage,
69+
onStreamComplete: function () use ($storage, $filePath, $folderName, $jobRunId): void {
70+
try {
71+
$storage->delete($filePath);
72+
$this->storageService->cleanUpFolder($folderName);
73+
$this->executionEngineService->hideJobRun($jobRunId);
74+
} catch (FilesystemException $e) {
75+
$this->logger->error(
76+
'Failed to clean up temporary folder {folder}',
77+
[
78+
'folder' => $folderName,
79+
'exception' => $e,
80+
]
81+
);
82+
}
83+
},
6784
);
68-
69-
try {
70-
$storage->delete($filePath);
71-
$this->storageService->cleanUpFolder($folderName);
72-
$this->executionEngineService->hideJobRun($jobRunId);
73-
} catch (FilesystemException) {
74-
throw new EnvironmentException(
75-
sprintf(
76-
'Failed to clean up temporary folder %s',
77-
$folderName
78-
)
79-
);
80-
}
81-
82-
return $streamedResponse;
8385
}
8486

8587
/**

src/Util/Trait/StreamedResponseTrait.php

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use Pimcore\Model\Asset\Thumbnail\ImageThumbnailInterface;
2424
use Pimcore\Model\Asset\Video;
2525
use Pimcore\Model\Asset\Video\ImageThumbnailInterface as VideoImageThumbnailInterface;
26+
use Closure;
2627
use Symfony\Component\HttpFoundation\StreamedResponse;
2728
use function is_resource;
2829
use function sprintf;
@@ -42,11 +43,12 @@ protected function getStreamedResponse(
4243
?int $fileSize = null,
4344
): StreamedResponse {
4445
$stream = $element->getStream();
46+
$asset = $this->getAsset($element);
4547

4648
if (!is_resource($stream)) {
4749
throw new ElementStreamResourceNotFoundException(
48-
$element->getId(),
49-
$element->getType()
50+
$asset->getId(),
51+
$asset->getType()
5052
);
5153
}
5254

@@ -62,7 +64,7 @@ function () use ($stream) {
6264
$this->getResponseHeaders(
6365
mimeType: $element->getMimeType(),
6466
fileSize: $fileSize,
65-
filename: $element->getFilename(),
67+
filename: $asset->getFilename(),
6668
contentDisposition: $contentDisposition,
6769
additionalHeaders: $additionalHeaders
6870
)
@@ -106,13 +108,17 @@ protected function getFileStreamedResponse(
106108
string $filename,
107109
FilesystemOperator $storage,
108110
string $contentDisposition = HttpResponseHeaders::ATTACHMENT_TYPE->value,
111+
?Closure $onStreamComplete = null,
109112
): StreamedResponse {
110113
try {
111114
$stream = $storage->readStream($path);
112115

113116
return new StreamedResponse(
114-
function () use ($stream) {
117+
function () use ($stream, $onStreamComplete) {
115118
fpassthru($stream);
119+
if ($onStreamComplete !== null) {
120+
$onStreamComplete();
121+
}
116122
},
117123
HttpResponseCodes::SUCCESS->value,
118124
$this->getResponseHeaders(
@@ -135,6 +141,15 @@ function () use ($stream) {
135141

136142
}
137143

144+
private function getAsset(Asset|VideoImageThumbnailInterface|ImageThumbnailInterface $element): Asset
145+
{
146+
if ($element instanceof Asset) {
147+
return $element;
148+
}
149+
150+
return $element->getAsset();
151+
}
152+
138153
private function getResponseHeaders(
139154
string $mimeType,
140155
int $fileSize,

0 commit comments

Comments
 (0)