forked from flashii/eeprom
Added thumbnail support for videos and embedded covers in audio.
This commit is contained in:
parent
5ab496b833
commit
a6ef98210c
2 changed files with 79 additions and 39 deletions
|
@ -132,6 +132,7 @@ if(preg_match('#^/uploads/([a-zA-Z0-9-_]{32})(\.t)?/?$#', $reqPath, $matches)) {
|
||||||
$uploadInfo->bumpExpiry();
|
$uploadInfo->bumpExpiry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$fileName = $uploadInfo->getName();
|
||||||
$contentType = $uploadInfo->getType();
|
$contentType = $uploadInfo->getType();
|
||||||
|
|
||||||
if($contentType === 'application/octet-stream' || substr($contentType, 0, 5) === 'text/')
|
if($contentType === 'application/octet-stream' || substr($contentType, 0, 5) === 'text/')
|
||||||
|
@ -139,49 +140,16 @@ if(preg_match('#^/uploads/([a-zA-Z0-9-_]{32})(\.t)?/?$#', $reqPath, $matches)) {
|
||||||
|
|
||||||
$sourceDir = basename($getThumbnail ? PRM_THUMBS : PRM_UPLOADS);
|
$sourceDir = basename($getThumbnail ? PRM_THUMBS : PRM_UPLOADS);
|
||||||
|
|
||||||
if($getThumbnail) {
|
if($getThumbnail && $uploadInfo->supportsThumbnail()) {
|
||||||
if(substr($contentType, 0, 6) !== 'image/') {
|
if(!is_file($uploadInfo->getThumbPath()))
|
||||||
http_response_code(404);
|
$uploadInfo->createThumbnail();
|
||||||
echo 'Thumbnails are not supported for this filetype.';
|
$contentType = 'image/jpeg';
|
||||||
return;
|
$fileName = pathinfo($fileName, PATHINFO_FILENAME) . '-thumb.jpg';
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
$imagick = new \Imagick($uploadInfo->getPath());
|
|
||||||
$imagick->setImageFormat('jpg');
|
|
||||||
$imagick->setImageCompressionQuality(40);
|
|
||||||
|
|
||||||
$thumbRes = 100;
|
|
||||||
$width = $imagick->getImageWidth();
|
|
||||||
$height = $imagick->getImageHeight();
|
|
||||||
|
|
||||||
if ($width > $height) {
|
|
||||||
$resizeWidth = $width * $thumbRes / $height;
|
|
||||||
$resizeHeight = $thumbRes;
|
|
||||||
} else {
|
|
||||||
$resizeWidth = $thumbRes;
|
|
||||||
$resizeHeight = $height * $thumbRes / $width;
|
|
||||||
}
|
|
||||||
|
|
||||||
$imagick->resizeImage(
|
|
||||||
$resizeWidth, $resizeHeight,
|
|
||||||
\Imagick::FILTER_GAUSSIAN, 0.7
|
|
||||||
);
|
|
||||||
|
|
||||||
$imagick->cropImage(
|
|
||||||
$thumbRes,
|
|
||||||
$thumbRes,
|
|
||||||
($resizeWidth - $thumbRes) / 2,
|
|
||||||
($resizeHeight - $thumbRes) / 2
|
|
||||||
);
|
|
||||||
|
|
||||||
$imagick->writeImage($uploadInfo->getThumbPath());
|
|
||||||
} catch(\Exception $ex) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
header(sprintf('X-Accel-Redirect: /%s/%s', $sourceDir, $uploadInfo->getId()));
|
header(sprintf('X-Accel-Redirect: /%s/%s', $sourceDir, $uploadInfo->getId()));
|
||||||
header(sprintf('Content-Type: %s', $contentType));
|
header(sprintf('Content-Type: %s', $contentType));
|
||||||
header(sprintf('Content-Disposition: inline; filename="%s"', addslashes($uploadInfo->getName())));
|
header(sprintf('Content-Disposition: inline; filename="%s"', addslashes($fileName)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
namespace EEPROM;
|
namespace EEPROM;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use Imagick;
|
||||||
use JsonSerializable;
|
use JsonSerializable;
|
||||||
|
|
||||||
class UploadNotFoundException extends Exception {};
|
class UploadNotFoundException extends Exception {};
|
||||||
|
@ -70,6 +71,15 @@ final class Upload implements JsonSerializable {
|
||||||
public function getType(): string {
|
public function getType(): string {
|
||||||
return $this->upload_type ?? 'text/plain';
|
return $this->upload_type ?? 'text/plain';
|
||||||
}
|
}
|
||||||
|
public function isImage(): bool {
|
||||||
|
return substr($this->getType(), 0, 6) === 'image/';
|
||||||
|
}
|
||||||
|
public function isVideo(): bool {
|
||||||
|
return substr($this->getType(), 0, 6) === 'video/';
|
||||||
|
}
|
||||||
|
public function isAudio(): bool {
|
||||||
|
return substr($this->getType(), 0, 6) === 'audio/';
|
||||||
|
}
|
||||||
|
|
||||||
public function getName(): string {
|
public function getName(): string {
|
||||||
return $this->upload_name ?? '';
|
return $this->upload_name ?? '';
|
||||||
|
@ -387,4 +397,66 @@ final class Upload implements JsonSerializable {
|
||||||
|
|
||||||
return $out;
|
return $out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function supportsThumbnail(): bool {
|
||||||
|
return $this->isImage() || $this->isAudio() || $this->isVideo();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createThumbnail(): void {
|
||||||
|
$tmpFile = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'eeprom' . bin2hex(random_bytes(10)) . '.jpg';
|
||||||
|
|
||||||
|
try {
|
||||||
|
if($this->isImage())
|
||||||
|
$imagick = new Imagick($this->getPath());
|
||||||
|
elseif($this->isAudio())
|
||||||
|
$imagick = $this->getCoverFromAudio($tmpFile);
|
||||||
|
elseif($this->isVideo())
|
||||||
|
$imagick = $this->getFrameFromVideo($tmpFile);
|
||||||
|
|
||||||
|
if(!isset($imagick))
|
||||||
|
return;
|
||||||
|
|
||||||
|
$imagick->setImageFormat('jpg');
|
||||||
|
$imagick->setImageCompressionQuality(40);
|
||||||
|
|
||||||
|
$thumbRes = 100;
|
||||||
|
$width = $imagick->getImageWidth();
|
||||||
|
$height = $imagick->getImageHeight();
|
||||||
|
|
||||||
|
if ($width > $height) {
|
||||||
|
$resizeWidth = $width * $thumbRes / $height;
|
||||||
|
$resizeHeight = $thumbRes;
|
||||||
|
} else {
|
||||||
|
$resizeWidth = $thumbRes;
|
||||||
|
$resizeHeight = $height * $thumbRes / $width;
|
||||||
|
}
|
||||||
|
|
||||||
|
$imagick->resizeImage(
|
||||||
|
$resizeWidth, $resizeHeight,
|
||||||
|
Imagick::FILTER_GAUSSIAN, 0.7
|
||||||
|
);
|
||||||
|
|
||||||
|
$imagick->cropImage(
|
||||||
|
$thumbRes,
|
||||||
|
$thumbRes,
|
||||||
|
($resizeWidth - $thumbRes) / 2,
|
||||||
|
($resizeHeight - $thumbRes) / 2
|
||||||
|
);
|
||||||
|
|
||||||
|
$imagick->writeImage($this->getThumbPath());
|
||||||
|
} catch(Exception $ex) {}
|
||||||
|
|
||||||
|
if(is_file($tmpFile))
|
||||||
|
unlink($tmpFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getFrameFromVideo(string $path): Imagick {
|
||||||
|
shell_exec(sprintf('ffmpeg -i %s -ss 00:00:01.000 -vframes 1 %s', $this->getPath(), $path));
|
||||||
|
return new Imagick($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getCoverFromAudio(string $path): Imagick {
|
||||||
|
shell_exec(sprintf('ffmpeg -i %s -an -vcodec copy %s', $this->getPath(), $path));
|
||||||
|
return new Imagick($path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue