aboutsummaryrefslogtreecommitdiffstats
path: root/lib/private/Preview
diff options
context:
space:
mode:
authorCôme Chilliet <91878298+come-nc@users.noreply.github.com>2023-04-20 16:52:38 +0200
committerGitHub <noreply@github.com>2023-04-20 16:52:38 +0200
commitb294edad804f40618a96116845615831302d0357 (patch)
tree71023e0f6d2185d44a4a62200e5613efa8aee089 /lib/private/Preview
parent8d5165e8dc40289b5d523523c4140f780b2fe293 (diff)
parent590c202797e6f5018635e45cdb2ed79ecd1c9865 (diff)
downloadnextcloud-server-b294edad804f40618a96116845615831302d0357.tar.gz
nextcloud-server-b294edad804f40618a96116845615831302d0357.zip
Merge branch 'master' into enh/type-iconfig-getter-calls
Signed-off-by: Côme Chilliet <91878298+come-nc@users.noreply.github.com>
Diffstat (limited to 'lib/private/Preview')
-rw-r--r--lib/private/Preview/Bundled.php4
-rw-r--r--lib/private/Preview/Generator.php140
2 files changed, 51 insertions, 93 deletions
diff --git a/lib/private/Preview/Bundled.php b/lib/private/Preview/Bundled.php
index df7f630dff7..2a408b90c4e 100644
--- a/lib/private/Preview/Bundled.php
+++ b/lib/private/Preview/Bundled.php
@@ -31,6 +31,10 @@ use OCP\IImage;
*/
abstract class Bundled extends ProviderV2 {
protected function extractThumbnail(File $file, string $path): ?IImage {
+ if ($file->getSize() === 0) {
+ return null;
+ }
+
$sourceTmp = \OC::$server->getTempManager()->getTemporaryFile();
$targetTmp = \OC::$server->getTempManager()->getTemporaryFile();
$this->tmpFiles[] = $sourceTmp;
diff --git a/lib/private/Preview/Generator.php b/lib/private/Preview/Generator.php
index 47f2952c6e6..ed9474fafb2 100644
--- a/lib/private/Preview/Generator.php
+++ b/lib/private/Preview/Generator.php
@@ -137,6 +137,8 @@ class Generator {
}
$previewFolder = $this->getPreviewFolder($file);
+ // List every existing preview first instead of trying to find them one by one
+ $previewFiles = $previewFolder->getDirectoryListing();
$previewVersion = '';
if ($file instanceof IVersionedPreviewFile) {
@@ -150,7 +152,7 @@ class Generator {
&& preg_match(Imaginary::supportedMimeTypes(), $mimeType)
&& $this->config->getSystemValueString('preview_imaginary_url', 'invalid') !== 'invalid') {
$crop = $specifications[0]['crop'] ?? false;
- $preview = $this->getSmallImagePreview($previewFolder, $file, $mimeType, $previewVersion, $crop);
+ $preview = $this->getSmallImagePreview($previewFolder, $previewFiles, $file, $mimeType, $previewVersion, $crop);
if ($preview->getSize() === 0) {
$preview->delete();
@@ -161,7 +163,7 @@ class Generator {
}
// Get the max preview and infer the max preview sizes from that
- $maxPreview = $this->getMaxPreview($previewFolder, $file, $mimeType, $previewVersion);
+ $maxPreview = $this->getMaxPreview($previewFolder, $previewFiles, $file, $mimeType, $previewVersion);
$maxPreviewImage = null; // only load the image when we need it
if ($maxPreview->getSize() === 0) {
$maxPreview->delete();
@@ -197,7 +199,7 @@ class Generator {
// Try to get a cached preview. Else generate (and store) one
try {
try {
- $preview = $this->getCachedPreview($previewFolder, $width, $height, $crop, $maxPreview->getMimeType(), $previewVersion);
+ $preview = $this->getCachedPreview($previewFiles, $width, $height, $crop, $maxPreview->getMimeType(), $previewVersion);
} catch (NotFoundException $e) {
if (!$this->previewManager->isMimeSupported($mimeType)) {
throw new NotFoundException();
@@ -208,6 +210,8 @@ class Generator {
}
$preview = $this->generatePreview($previewFolder, $maxPreviewImage, $width, $height, $crop, $maxWidth, $maxHeight, $previewVersion);
+ // New file, augment our array
+ $previewFiles[] = $preview;
}
} catch (\InvalidArgumentException $e) {
throw new NotFoundException("", 0, $e);
@@ -233,75 +237,19 @@ class Generator {
* Generate a small image straight away without generating a max preview first
* Preview generated is 256x256
*
+ * @param ISimpleFile[] $previewFiles
+ *
* @throws NotFoundException
*/
- private function getSmallImagePreview(ISimpleFolder $previewFolder, File $file, string $mimeType, string $prefix, bool $crop): ISimpleFile {
- $nodes = $previewFolder->getDirectoryListing();
-
- foreach ($nodes as $node) {
- $name = $node->getName();
- if (($prefix === '' || str_starts_with($name, $prefix))) {
- // Prefix match
- if (str_starts_with($name, $prefix . '256-256-crop') && $crop) {
- // Cropped image
- return $node;
- }
-
- if (str_starts_with($name, $prefix . '256-256.') && !$crop) {
- // Uncropped image
- return $node;
- }
- }
- }
-
- $previewProviders = $this->previewManager->getProviders();
- foreach ($previewProviders as $supportedMimeType => $providers) {
- // Filter out providers that does not support this mime
- if (!preg_match($supportedMimeType, $mimeType)) {
- continue;
- }
-
- foreach ($providers as $providerClosure) {
- $provider = $this->helper->getProvider($providerClosure);
- if (!($provider instanceof IProviderV2)) {
- continue;
- }
-
- if (!$provider->isAvailable($file)) {
- continue;
- }
-
- $preview = $this->helper->getThumbnail($provider, $file, 256, 256, $crop);
-
- if (!($preview instanceof IImage)) {
- continue;
- }
-
- // Try to get the extension.
- try {
- $ext = $this->getExtention($preview->dataMimeType());
- } catch (\InvalidArgumentException $e) {
- // Just continue to the next iteration if this preview doesn't have a valid mimetype
- continue;
- }
-
- $path = $this->generatePath(256, 256, $crop, $preview->dataMimeType(), $prefix);
- try {
- $file = $previewFolder->newFile($path);
- if ($preview instanceof IStreamImage) {
- $file->putContent($preview->resource());
- } else {
- $file->putContent($preview->data());
- }
- } catch (NotPermittedException $e) {
- throw new NotFoundException();
- }
+ private function getSmallImagePreview(ISimpleFolder $previewFolder, array $previewFiles, File $file, string $mimeType, string $prefix, bool $crop): ISimpleFile {
+ $width = 256;
+ $height = 256;
- return $file;
- }
+ try {
+ return $this->getCachedPreview($previewFiles, $width, $height, $crop, $mimeType, $prefix);
+ } catch (NotFoundException $e) {
+ return $this->generateProviderPreview($previewFolder, $file, $width, $height, $crop, false, $mimeType, $prefix);
}
-
- throw new NotFoundException('No provider successfully handled the preview generation');
}
/**
@@ -398,22 +346,30 @@ class Generator {
/**
* @param ISimpleFolder $previewFolder
+ * @param ISimpleFile[] $previewFiles
* @param File $file
* @param string $mimeType
* @param string $prefix
* @return ISimpleFile
* @throws NotFoundException
*/
- private function getMaxPreview(ISimpleFolder $previewFolder, File $file, $mimeType, $prefix) {
- $nodes = $previewFolder->getDirectoryListing();
-
- foreach ($nodes as $node) {
+ private function getMaxPreview(ISimpleFolder $previewFolder, array $previewFiles, File $file, $mimeType, $prefix) {
+ // We don't know the max preview size, so we can't use getCachedPreview.
+ // It might have been generated with a higher resolution than the current value.
+ foreach ($previewFiles as $node) {
$name = $node->getName();
if (($prefix === '' || strpos($name, $prefix) === 0) && strpos($name, 'max')) {
return $node;
}
}
+ $maxWidth = $this->config->getSystemValueInt('preview_max_x', 4096);
+ $maxHeight = $this->config->getSystemValueInt('preview_max_y', 4096);
+
+ return $this->generateProviderPreview($previewFolder, $file, $maxWidth, $maxHeight, false, true, $mimeType, $prefix);
+ }
+
+ private function generateProviderPreview(ISimpleFolder $previewFolder, File $file, int $width, int $height, bool $crop, bool $max, string $mimeType, string $prefix) {
$previewProviders = $this->previewManager->getProviders();
foreach ($previewProviders as $supportedMimeType => $providers) {
// Filter out providers that does not support this mime
@@ -431,13 +387,10 @@ class Generator {
continue;
}
- $maxWidth = $this->config->getSystemValueInt('preview_max_x', 4096);
- $maxHeight = $this->config->getSystemValueInt('preview_max_y', 4096);
-
$previewConcurrency = $this->getNumConcurrentPreviews('preview_concurrency_new');
$sem = self::guardWithSemaphore(self::SEMAPHORE_ID_NEW, $previewConcurrency);
try {
- $preview = $this->helper->getThumbnail($provider, $file, $maxWidth, $maxHeight);
+ $preview = $this->helper->getThumbnail($provider, $file, $width, $height);
} finally {
self::unguardWithSemaphore($sem);
}
@@ -446,15 +399,7 @@ class Generator {
continue;
}
- // Try to get the extention.
- try {
- $ext = $this->getExtention($preview->dataMimeType());
- } catch (\InvalidArgumentException $e) {
- // Just continue to the next iteration if this preview doesn't have a valid mimetype
- continue;
- }
-
- $path = $prefix . (string)$preview->width() . '-' . (string)$preview->height() . '-max.' . $ext;
+ $path = $this->generatePath($preview->width(), $preview->height(), $crop, $max, $preview->dataMimeType(), $prefix);
try {
$file = $previewFolder->newFile($path);
if ($preview instanceof IStreamImage) {
@@ -470,7 +415,7 @@ class Generator {
}
}
- throw new NotFoundException();
+ throw new NotFoundException('No provider successfully handled the preview generation');
}
/**
@@ -487,15 +432,19 @@ class Generator {
* @param int $width
* @param int $height
* @param bool $crop
+ * @param bool $max
* @param string $mimeType
* @param string $prefix
* @return string
*/
- private function generatePath($width, $height, $crop, $mimeType, $prefix) {
+ private function generatePath($width, $height, $crop, $max, $mimeType, $prefix) {
$path = $prefix . (string)$width . '-' . (string)$height;
if ($crop) {
$path .= '-crop';
}
+ if ($max) {
+ $path .= '-max';
+ }
$ext = $this->getExtention($mimeType);
$path .= '.' . $ext;
@@ -637,7 +586,8 @@ class Generator {
self::unguardWithSemaphore($sem);
}
- $path = $this->generatePath($width, $height, $crop, $preview->dataMimeType(), $prefix);
+
+ $path = $this->generatePath($width, $height, $crop, false, $preview->dataMimeType(), $prefix);
try {
$file = $previewFolder->newFile($path);
$file->putContent($preview->data());
@@ -649,7 +599,7 @@ class Generator {
}
/**
- * @param ISimpleFolder $previewFolder
+ * @param ISimpleFile[] $files Array of FileInfo, as the result of getDirectoryListing()
* @param int $width
* @param int $height
* @param bool $crop
@@ -659,10 +609,14 @@ class Generator {
*
* @throws NotFoundException
*/
- private function getCachedPreview(ISimpleFolder $previewFolder, $width, $height, $crop, $mimeType, $prefix) {
- $path = $this->generatePath($width, $height, $crop, $mimeType, $prefix);
-
- return $previewFolder->getFile($path);
+ private function getCachedPreview($files, $width, $height, $crop, $mimeType, $prefix) {
+ $path = $this->generatePath($width, $height, $crop, false, $mimeType, $prefix);
+ foreach ($files as $file) {
+ if ($file->getName() === $path) {
+ return $file;
+ }
+ }
+ throw new NotFoundException();
}
/**