diff --git a/src/Controller/ImageStyleRedirectController.php b/src/Controller/ImageStyleRedirectController.php index e03ddf8..fd3641d 100644 --- a/src/Controller/ImageStyleRedirectController.php +++ b/src/Controller/ImageStyleRedirectController.php @@ -124,7 +124,7 @@ class ImageStyleRedirectController extends ImageStyleDownloadController { */ protected function generateTemporaryImage($scheme, $source_path, ImageStyleInterface $image_style) { $image_uri = "$scheme://$source_path"; - $destination_temp = $image_style->buildUri("temporary://flysystem/$scheme/$source_path"); + $destination_temp = $this->getTemporaryDestination($scheme, $source_path, $image_style); // Try to generate the temporary image, watching for other threads that may // also be trying to generate the temporary image. @@ -193,15 +193,9 @@ class ImageStyleRedirectController extends ImageStyleDownloadController { // https://www.drupal.org/node/2630808 // http://drupal.stackexchange.com/questions/187086/trustedresponseredirect-failing-how-to-prevent-cache-metadata - // @todo Figure out why caching this response leads to stale images being - // served. - - // $url = Url::fromUri($image_style->buildUrl($source_uri))->toString(TRUE); - // $response = new TrustedRedirectResponse($url->getGeneratedUrl()); - // $response->addCacheableDependency($url); - - $response = new TrustedRedirectResponse($image_style->buildUrl($source_uri)); - $response->addCacheableDependency(0); + $url = Url::fromUri($image_style->buildUrl($source_uri))->toString(TRUE); + $response = new TrustedRedirectResponse($url->getGeneratedUrl()); + $response->addCacheableDependency($url); return $response; } @@ -224,11 +218,23 @@ class ImageStyleRedirectController extends ImageStyleDownloadController { */ protected function deliverTemporary($scheme, $source_path, ImageStyleInterface $image_style) { $source_uri = $scheme . '://' . $source_path; - $derivative_uri = $image_style->buildUri($source_uri); + + // Try to serve the temporary image if possible. Load into memory, since it + // can be delted at any point. + $destination_temp = $this->getTemporaryDestination($scheme, $source_path, $image_style); + + if (file_exists($destination_temp)) { + $temp_content = @file_get_contents($destination_temp); + if ($temp_content !== FALSE) { + return $this->sendRawImage($destination_temp, $temp_content); + } + } + try { $temporary_uri = $this->generateTemporaryImage($scheme, $source_path, $image_style); } catch (\RuntimeException $e) { + $derivative_uri = $image_style->buildUri($source_uri); $this->logger->notice('Unable to generate the derived image located at %path.', ['%path' => $derivative_uri]); return new Response($this->t('Error generating image.'), 500); } @@ -252,4 +258,43 @@ class ImageStyleRedirectController extends ImageStyleDownloadController { return $this->send($scheme, $temporary_uri); } + /** + * Returns the temporary image path. + * + * @param string $scheme + * The scheme of the source image. + * @param string $source_path + * The path of the source image. + * @param \Drupal\image\ImageStyleInterface $image_style + * The image style to generate. + * + * @return string + * The temporary image path. + */ + protected function getTemporaryDestination($scheme, $source_path, ImageStyleInterface $image_style) { + return $image_style->buildUri("temporary://flysystem/$scheme/$source_path"); + } + + /** + * Returns a response of the derived raw image. + * + * @param string $path + * The file path. + * @param string $image_content + * The image contents. + * @param array $headers + * (optional) An array of headers to return in the response. + * + * @return \Symfony\Component\HttpFoundation\Response + * A response with the derived image. + */ + protected function sendRawImage($path, $image_content, $headers = []) { + $headers += [ + 'Content-Type' => \Drupal::service('file.mime_type.guesser.extension')->guess($path), + 'Content-Length' => strlen($image_content), + ]; + + return new Response($image_content, 200, $headers); + } + } diff --git a/src/ImageStyleCopier.php b/src/ImageStyleCopier.php index 5b913df..102daaf 100644 --- a/src/ImageStyleCopier.php +++ b/src/ImageStyleCopier.php @@ -152,6 +152,7 @@ class ImageStyleCopier implements EventSubscriberInterface, ContainerInjectionIn } finally { + file_unmanaged_delete($temporary_uri); $this->lock->release($lock_name); } } diff --git a/src/PathProcessor/FlysystemImageStyleRedirectProcessor.php b/src/PathProcessor/FlysystemImageStyleRedirectProcessor.php index 735256d..51a06c9 100644 --- a/src/PathProcessor/FlysystemImageStyleRedirectProcessor.php +++ b/src/PathProcessor/FlysystemImageStyleRedirectProcessor.php @@ -23,7 +23,7 @@ class FlysystemImageStyleRedirectProcessor implements InboundPathProcessorInterf */ public function processInbound($path, Request $request) { // Quick exit. - if (strpos($path, static::STYLES_PATH) !== 0) { + if (strpos($path, static::STYLES_PATH . '/') !== 0) { return $path; } @@ -41,7 +41,7 @@ class FlysystemImageStyleRedirectProcessor implements InboundPathProcessorInterf // Set the file as query parameter. $request->query->set('file', $file); - return static::STYLES_PATH . '/' . $image_style . '/' . $scheme; + return static::STYLES_PATH . '/' . $image_style . '/' . $scheme . '/' . hash('sha256', $file); } }