Files
lucent-laravel/src/File/FileService.php
T

167 lines
5.2 KiB
PHP
Raw Normal View History

2023-10-02 23:10:49 +03:00
<?php
namespace Lucent\File;
2024-08-19 17:48:10 +03:00
use Exception;
use Illuminate\Contracts\Filesystem\Filesystem;
2023-10-02 23:10:49 +03:00
use Illuminate\Http\UploadedFile;
2024-08-19 17:48:10 +03:00
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Intervention\Image\ImageManagerStatic;
2023-10-04 13:32:30 +03:00
use Lucent\Channel\ChannelService;
2024-09-07 13:22:58 +03:00
use Lucent\Database\Database;
2023-10-02 23:10:49 +03:00
use Lucent\LucentException;
2024-08-19 17:48:10 +03:00
use Lucent\Record\FileData as RecordFile;
2023-10-04 13:32:30 +03:00
use Lucent\Record\QueryRecord;
2024-08-19 17:48:10 +03:00
use Lucent\Schema\FilesSchema;
use Spatie\ImageOptimizer\OptimizerChainFactory;
2023-10-02 23:10:49 +03:00
class FileService
{
2023-10-04 13:32:30 +03:00
public function __construct(
public ChannelService $channelService
)
2023-10-02 23:10:49 +03:00
{
}
2023-10-04 13:32:30 +03:00
public function getPath(QueryRecord $file): string
{
2024-08-23 20:58:45 +03:00
return $this->channelService->channel->filesUrl . "/" . $file->_file->path;
2023-10-04 13:32:30 +03:00
}
2024-08-19 17:48:10 +03:00
public function createFromUrl(FilesSchema $schema, string $url): FileUploadResult
2023-10-02 23:10:49 +03:00
{
2024-08-19 17:48:10 +03:00
$pathinfo = pathinfo($url);
$contents = file_get_contents($url);
if ($contents === false) {
throw new LucentException("Failed to upload file from url");
}
$file = '/tmp/' . $pathinfo['basename'];
file_put_contents($file, $contents);
$uploadedFile = new UploadedFile($file, $pathinfo['basename']);
return $this->upload($schema, $uploadedFile);
}
public function upload(FilesSchema $schema, UploadedFile $file): FileUploadResult
{
$originalName = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
$extension = pathinfo($file->getClientOriginalName(), PATHINFO_EXTENSION);
$originalFilename = $file->getClientOriginalName();
$filename = $this->createFileName($originalName, $extension);
$mimetype = $file->getMimeType();
$optimizerChain = OptimizerChainFactory::create();
$optimizerChain->setTimeout(30)->optimize($file->getPathName());
$checksum = sha1_file($file);
$recordId = $this->checkDuplicate($schema->name, $checksum, $file->getSize());
if (!empty($recordId)) {
2023-10-02 23:10:49 +03:00
return new FileUploadResult(
2024-08-19 17:48:10 +03:00
recordFile: null,
duplicateId: $recordId,
isDuplicate: true
2023-10-02 23:10:49 +03:00
);
}
2024-08-19 17:48:10 +03:00
$disk = $this->loadDisk();
$path = $schema->path . "/" . $filename;
$res = $disk->put(
$path,
file_get_contents($file),
// 'public' // now managed by aws policy
);
if ($res === false) {
throw new LucentException("File $filename not uploaded");
2023-10-02 23:10:49 +03:00
}
2024-08-19 17:48:10 +03:00
$this->createThumbnail($disk, $schema->path, $filename, $file);
list($width, $height) = $this->isImage($mimetype) ? getimagesize($file) : [0, 0];
$recordFile = new RecordFile(
originalName: $originalFilename,
mime: $mimetype,
path: $path,
size: $file->getSize(),
width: $width,
height: $height,
checksum: $checksum
);
2023-10-02 23:10:49 +03:00
return new FileUploadResult(
2024-08-19 17:48:10 +03:00
recordFile: $recordFile,
duplicateId: "",
isDuplicate: false
2023-10-02 23:10:49 +03:00
);
}
2024-08-19 17:48:10 +03:00
private function createFileName(string $originalName, string $extension): string
2023-10-02 23:10:49 +03:00
{
2024-08-19 17:48:10 +03:00
return Str::slug($originalName, '-') . '-' . uniqid() . '.' . $extension;
}
2023-10-02 23:10:49 +03:00
2024-08-19 17:48:10 +03:00
private function isImage(string $mimetype): bool
{
$imageMimes = ['image/webp', 'image/gif', 'image/jpeg', 'image/png', 'image/tiff'];
return in_array($mimetype, $imageMimes);
}
public function loadDisk(): Filesystem
{
2024-08-23 20:58:45 +03:00
return Storage::disk('lucent');
2024-08-19 17:48:10 +03:00
return Storage::build([
2024-08-23 20:58:45 +03:00
'driver' => 'lucent',
2024-08-19 17:48:10 +03:00
// 'key' => config("filesystems.disks.s3.key"),
// 'secret' => config("filesystems.disks.s3.secret"),
// 'region' => config("filesystems.disks.s3.region"),
// 'bucket' => config("filesystems.disks.s3.bucket"),
// // 'url' => $schema->objectStorageUrl,
// 'endpoint' => $schema->objectStorageEndpoint,
2024-08-23 20:58:45 +03:00
// 'use_path_style_endpoint' => false,
2024-08-19 17:48:10 +03:00
'visibility' => 'public', // now managed by aws policy
'root' => storage_path('app/public'),
'throw' => true,
]);
}
private function checkDuplicate(string $schemaName, string $checksum, int $filesize): string
{
2024-09-07 13:22:58 +03:00
$record = Database::make()->table("records")
2024-08-19 17:48:10 +03:00
->where("schema", $schemaName)
->where("_file->checksum", $checksum)
->where("_file->size", $filesize)
->first();
return $record->id ?? "";
}
private function createThumbnail(Filesystem $disk, string $schemaPath, string $filename, UploadedFile $file): void
{
2024-08-23 20:58:45 +03:00
$thumbDir = "thumbs/" . $schemaPath . "/";
// if (!file_exists($thumbDir)) {
// make_dir_r($thumbDir);
// }
2024-08-19 17:48:10 +03:00
try {
ImageManagerStatic::configure(['driver' => 'imagick']);
$image = ImageManagerStatic::make($file);
} catch (Exception $e) {
logger($e->getMessage());
return;
}
$image->fit(300, 300);
try {
2024-08-23 20:58:45 +03:00
$this->loadDisk()->put($thumbDir . $filename, $image->encode('webp', 75));
// $image->encode('webp', 75)->save($thumbDir . $filename);
2024-08-19 17:48:10 +03:00
} catch (Exception $e) {
logger($e->getMessage());
2023-10-02 23:10:49 +03:00
}
}
2024-08-19 17:48:10 +03:00
2023-10-02 23:10:49 +03:00
}