feat(previews): Support in memory preview request

This allows callers to use the API without increasing the disk usage.

Example: blurhash generation, where we request a preview for all uploaded pictures, but don't want to necessarily store that preview.
Signed-off-by: Louis Chemineau <louis@chmn.me>
pull/52360/head
Louis Chemineau 6 months ago
parent ed485a9731
commit 2238548278
No known key found for this signature in database
  1. 57
      lib/private/Preview/Generator.php
  2. 29
      lib/private/PreviewManager.php
  3. 4
      lib/public/IPreview.php

@ -12,6 +12,7 @@ use OCP\Files\IAppData;
use OCP\Files\InvalidPathException;
use OCP\Files\NotFoundException;
use OCP\Files\NotPermittedException;
use OCP\Files\SimpleFS\InMemoryFile;
use OCP\Files\SimpleFS\ISimpleFile;
use OCP\Files\SimpleFS\ISimpleFolder;
use OCP\IConfig;
@ -43,17 +44,19 @@ class Generator {
* The cache is searched first and if nothing usable was found then a preview is
* generated by one of the providers
*
* @param File $file
* @param int $width
* @param int $height
* @param bool $crop
* @param string $mode
* @param string|null $mimeType
* @return ISimpleFile
* @throws NotFoundException
* @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid)
*/
public function getPreview(File $file, $width = -1, $height = -1, $crop = false, $mode = IPreview::MODE_FILL, $mimeType = null) {
public function getPreview(
File $file,
int $width = -1,
int $height = -1,
bool $crop = false,
string $mode = IPreview::MODE_FILL,
?string $mimeType = null,
bool $cacheResult = true,
): ISimpleFile {
$specification = [
'width' => $width,
'height' => $height,
@ -78,23 +81,19 @@ class Generator {
'mode' => $mode,
'mimeType' => $mimeType,
]);
// since we only ask for one preview, and the generate method return the last one it created, it returns the one we want
return $this->generatePreviews($file, [$specification], $mimeType);
return $this->generatePreviews($file, [$specification], $mimeType, $cacheResult);
}
/**
* Generates previews of a file
*
* @param File $file
* @param non-empty-array $specifications
* @param string $mimeType
* @return ISimpleFile the last preview that was generated
* @throws NotFoundException
* @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid)
*/
public function generatePreviews(File $file, array $specifications, $mimeType = null) {
public function generatePreviews(File $file, array $specifications, ?string $mimeType = null, bool $cacheResult = true): ISimpleFile {
//Make sure that we can read the file
if (!$file->isReadable()) {
$this->logger->warning('Cannot read file: {path}, skipping preview generation.', ['path' => $file->getPath()]);
@ -167,7 +166,7 @@ class Generator {
}
$this->logger->warning('Cached preview not found for file {path}, generating a new preview.', ['path' => $file->getPath()]);
$preview = $this->generatePreview($previewFolder, $maxPreviewImage, $width, $height, $crop, $maxWidth, $maxHeight, $previewVersion);
$preview = $this->generatePreview($previewFolder, $maxPreviewImage, $width, $height, $crop, $maxWidth, $maxHeight, $previewVersion, $cacheResult);
// New file, augment our array
$previewFiles[] = $preview;
}
@ -490,19 +489,20 @@ class Generator {
}
/**
* @param ISimpleFolder $previewFolder
* @param ISimpleFile $maxPreview
* @param int $width
* @param int $height
* @param bool $crop
* @param int $maxWidth
* @param int $maxHeight
* @param string $prefix
* @return ISimpleFile
* @throws NotFoundException
* @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid)
*/
private function generatePreview(ISimpleFolder $previewFolder, IImage $maxPreview, $width, $height, $crop, $maxWidth, $maxHeight, $prefix) {
private function generatePreview(
ISimpleFolder $previewFolder,
IImage $maxPreview,
int $width,
int $height,
bool $crop,
int $maxWidth,
int $maxHeight,
string $prefix,
bool $cacheResult,
): ISimpleFile {
$preview = $maxPreview;
if (!$preview->valid()) {
throw new \InvalidArgumentException('Failed to generate preview, failed to load image');
@ -539,8 +539,11 @@ class Generator {
$path = $this->generatePath($width, $height, $crop, false, $preview->dataMimeType(), $prefix);
try {
$file = $previewFolder->newFile($path);
$file->putContent($preview->data());
if ($cacheResult) {
$file = $previewFolder->newFile($path, $preview->data());
} else {
return new InMemoryFile($path, $preview->data());
}
} catch (NotPermittedException $e) {
throw new NotFoundException();
}

@ -145,29 +145,20 @@ class PreviewManager implements IPreview {
return $this->generator;
}
/**
* Returns a preview of a file
*
* The cache is searched first and if nothing usable was found then a preview is
* generated by one of the providers
*
* @param File $file
* @param int $width
* @param int $height
* @param bool $crop
* @param string $mode
* @param string $mimeType
* @return ISimpleFile
* @throws NotFoundException
* @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid)
* @since 11.0.0 - \InvalidArgumentException was added in 12.0.0
*/
public function getPreview(File $file, $width = -1, $height = -1, $crop = false, $mode = IPreview::MODE_FILL, $mimeType = null) {
public function getPreview(
File $file,
$width = -1,
$height = -1,
$crop = false,
$mode = IPreview::MODE_FILL,
$mimeType = null,
bool $cacheResult = true,
): ISimpleFile {
$this->throwIfPreviewsDisabled();
$previewConcurrency = $this->getGenerator()->getNumConcurrentPreviews('preview_concurrency_all');
$sem = Generator::guardWithSemaphore(Generator::SEMAPHORE_ID_ALL, $previewConcurrency);
try {
$preview = $this->getGenerator()->getPreview($file, $width, $height, $crop, $mode, $mimeType);
$preview = $this->getGenerator()->getPreview($file, $width, $height, $crop, $mode, $mimeType, $cacheResult);
} finally {
Generator::unguardWithSemaphore($sem);
}

@ -71,12 +71,14 @@ interface IPreview {
* @param bool $crop
* @param string $mode
* @param string $mimeType To force a given mimetype for the file (files_versions needs this)
* @param bool $cacheResult Whether or not to cache the preview on the filesystem. Default to true. Can be useful to set to false to limit the amount of stored previews.
* @return ISimpleFile
* @throws NotFoundException
* @throws \InvalidArgumentException if the preview would be invalid (in case the original image is invalid)
* @since 11.0.0 - \InvalidArgumentException was added in 12.0.0
* @since 32.0.0 - getPreview($cacheResult) added the $cacheResult argument to the signature
*/
public function getPreview(File $file, $width = -1, $height = -1, $crop = false, $mode = IPreview::MODE_FILL, $mimeType = null);
public function getPreview(File $file, $width = -1, $height = -1, $crop = false, $mode = IPreview::MODE_FILL, $mimeType = null, bool $cacheResult = true);
/**
* Returns true if the passed mime type is supported

Loading…
Cancel
Save