From 09bb8fe6df4c395ffc5cc0f215439b4132f8269f Mon Sep 17 00:00:00 2001 From: Mathias Schreiber <mathias.schreiber@typo3.org> Date: Fri, 20 Apr 2018 21:23:35 +0200 Subject: [PATCH] [BUGFIX] Decouple thumbnail generation from controllers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deferred rendering of thumbnails via an external request speed up the backend performance. This currently works in all places that use BackendUtility::thumbsCode. Resolves: #85605 Releases: master, 8.7 Change-Id: Id5635fc9cd340b8bcf21995cd457415aaa1a8926 Reviewed-on: https://review.typo3.org/56765 Reviewed-by: Benjamin Kott <benjamin.kott@outlook.com> Tested-by: Benjamin Kott <benjamin.kott@outlook.com> Tested-by: TYPO3com <no-reply@typo3.com> Reviewed-by: Jörg Bösche <typo3@joergboesche.de> Reviewed-by: Frank Naegler <frank.naegler@typo3.org> Tested-by: Frank Naegler <frank.naegler@typo3.org> --- .../Controller/File/ThumbnailController.php | 63 +++++++++++++++++++ .../Classes/Utility/BackendUtility.php | 30 +++++---- .../backend/Configuration/Backend/Routes.php | 6 ++ 3 files changed, 86 insertions(+), 13 deletions(-) create mode 100644 typo3/sysext/backend/Classes/Controller/File/ThumbnailController.php diff --git a/typo3/sysext/backend/Classes/Controller/File/ThumbnailController.php b/typo3/sysext/backend/Classes/Controller/File/ThumbnailController.php new file mode 100644 index 000000000000..734c13b0f4f6 --- /dev/null +++ b/typo3/sysext/backend/Classes/Controller/File/ThumbnailController.php @@ -0,0 +1,63 @@ +<?php +declare(strict_types = 1); +namespace TYPO3\CMS\Backend\Controller\File; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use TYPO3\CMS\Core\Http\Response; +use TYPO3\CMS\Core\Resource\File; +use TYPO3\CMS\Core\Resource\ProcessedFile; +use TYPO3\CMS\Core\Resource\ResourceFactory; +use TYPO3\CMS\Core\Utility\ArrayUtility; + +/** + * Class ThumbnailController + */ +class ThumbnailController +{ + /** + * @param ServerRequestInterface $request + * @return ResponseInterface + */ + public function render(ServerRequestInterface $request): ResponseInterface + { + $fileObject = $this->getFileObjectByCombinedIdentifier($request->getQueryParams()['fileIdentifier']); + if (!$fileObject->isMissing()) { + $processingInstructions = [ + 'width' => 64, + 'height' => 64, + 'crop' => null, + ]; + ArrayUtility::mergeRecursiveWithOverrule($processingInstructions, $request->getQueryParams()['processingInstructions']); + $processedImage = $fileObject->process(ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, $processingInstructions); + $filePath = $processedImage->getForLocalProcessing(false); + return new Response($filePath, 200, [ + 'Content-Type' => $processedImage->getMimeType() + ]); + } + return new Response('', 404); + } + + /** + * @param string $combinedIdentifier + * @return File + * @throws \InvalidArgumentException + */ + protected function getFileObjectByCombinedIdentifier(string $combinedIdentifier): File + { + return ResourceFactory::getInstance()->getFileObjectFromCombinedIdentifier($combinedIdentifier); + } +} diff --git a/typo3/sysext/backend/Classes/Utility/BackendUtility.php b/typo3/sysext/backend/Classes/Utility/BackendUtility.php index c953e3146fbe..97210c14d38d 100644 --- a/typo3/sysext/backend/Classes/Utility/BackendUtility.php +++ b/typo3/sysext/backend/Classes/Utility/BackendUtility.php @@ -1353,19 +1353,23 @@ class BackendUtility ) { $cropVariantCollection = CropVariantCollection::create((string)$fileReferenceObject->getProperty('crop')); $cropArea = $cropVariantCollection->getCropArea(); - $processedImage = $fileObject->process( - ProcessedFile::CONTEXT_IMAGECROPSCALEMASK, - [ - 'width' => $sizeParts[0], - 'height' => $sizeParts[1] . 'c', - 'crop' => $cropArea->isEmpty() ? null : $cropArea->makeAbsoluteBasedOnFile($fileReferenceObject) - ] - ); - $imageUrl = $processedImage->getPublicUrl(true); - $imgTag = '<img src="' . $imageUrl . '" ' - . 'width="' . $processedImage->getProperty('width') . '" ' - . 'height="' . $processedImage->getProperty('height') . '" ' - . 'alt="' . htmlspecialchars($fileReferenceObject->getName()) . '" />'; + $processingInformation = [ + 'width' => $sizeParts[0], + 'height' => $sizeParts[1] . 'c', + 'crop' => $cropArea->isEmpty() ? null : $cropArea->makeAbsoluteBasedOnFile($fileReferenceObject) + ]; + $imageUrl = (string)GeneralUtility::makeInstance(UriBuilder::class) + ->buildUriFromRoute('thumbnails', [ + 'fileIdentifier' => $fileObject->getCombinedIdentifier(), + 'processingInstructions' => $processingInformation + ]); + $attributes = [ + 'src' => $imageUrl, + 'width' => (int)$sizeParts[0], + 'height' => (int)$sizeParts[1], + 'alt' => $fileReferenceObject->getName(), + ]; + $imgTag = '<img ' . GeneralUtility::implodeAttributes($attributes, true) . '/>'; } else { // Icon $imgTag = '<span title="' . htmlspecialchars($fileObject->getName()) . '">' diff --git a/typo3/sysext/backend/Configuration/Backend/Routes.php b/typo3/sysext/backend/Configuration/Backend/Routes.php index 2dd6c3a55256..0429aad12d02 100644 --- a/typo3/sysext/backend/Configuration/Backend/Routes.php +++ b/typo3/sysext/backend/Configuration/Backend/Routes.php @@ -207,5 +207,11 @@ return [ 'record_edit' => [ 'path' => '/record/edit', 'target' => Controller\EditDocumentController::class . '::mainAction' + ], + + // Thumbnails + 'thumbnails' => [ + 'path' => '/thumbnails', + 'target' => Controller\File\ThumbnailController::class . '::render' ] ]; -- GitLab