126 lines
3.7 KiB
PHP
126 lines
3.7 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\Medium;
|
|
use Illuminate\Http\UploadedFile;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Support\Str;
|
|
|
|
class FileStorageService
|
|
{
|
|
public function storeFile(UploadedFile $file, string $disk = 'public', string $directory = 'files'): Medium
|
|
{
|
|
$diskInstance = Storage::disk($disk);
|
|
$filename = $this->generateUniqueFilename($file);
|
|
$path = $directory . '/' . $filename;
|
|
$visibility = $disk === 'public' ? 'public' : 'private';
|
|
|
|
DB::beginTransaction();
|
|
try {
|
|
$diskInstance->putFileAs($directory, $file, $filename, ['visibility' => $visibility]);
|
|
|
|
$medium = Medium::create([
|
|
'filename' => $filename,
|
|
'disk' => $disk,
|
|
'path' => $path,
|
|
'url' => $visibility === 'public' ? Storage::disk('public')->url($path) : null,
|
|
'size' => $file->getSize(),
|
|
'mime_type' => $file->getMimeType(),
|
|
]);
|
|
|
|
DB::commit();
|
|
return $medium;
|
|
} catch (\Throwable $e) {
|
|
DB::rollBack();
|
|
if ($diskInstance->exists($path)) {
|
|
$diskInstance->delete($path);
|
|
}
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
public function moveToDisk(Medium $medium, string $newDisk): bool
|
|
{
|
|
if ($medium->disk->value === $newDisk) return true;
|
|
|
|
$old = Storage::disk($medium->disk->value);
|
|
$new = Storage::disk($newDisk);
|
|
|
|
$stream = $old->readStream($medium->path);
|
|
if ($stream === false) return false;
|
|
|
|
$new->put($medium->path, $stream);
|
|
if (is_resource($stream)) fclose($stream);
|
|
|
|
if ($newDisk === 'public') {
|
|
$new->setVisibility($medium->path, 'public');
|
|
$medium->url = Storage::disk('public')->url($medium->path);
|
|
} else {
|
|
$medium->url = null;
|
|
}
|
|
|
|
$old->delete($medium->path);
|
|
$medium->disk = $newDisk;
|
|
$medium->save();
|
|
|
|
return true;
|
|
}
|
|
|
|
public function deleteMedium(Medium $medium): mixed
|
|
{
|
|
$disk = Storage::disk($medium->disk->value);
|
|
if ($disk->exists($medium->path)) {
|
|
$disk->delete($medium->path);
|
|
}
|
|
return $medium->delete();
|
|
}
|
|
|
|
public function downloadFile(Medium $medium)
|
|
{
|
|
if (!$medium->isPrivate()) {
|
|
abort(404, 'فایل مورد نظر یافت نشد.');
|
|
}
|
|
|
|
if (!$medium->exists()) {
|
|
abort(404, 'فایل مورد نظر یافت نشد.');
|
|
}
|
|
|
|
return response()->download(
|
|
$medium->getStorageDisk()->path($medium->path),
|
|
$medium->filename
|
|
);
|
|
}
|
|
|
|
public function serveFile(Medium $medium)
|
|
{
|
|
if (!$medium->isPrivate()) {
|
|
abort(404, 'فایل مورد نظر یافت نشد.');
|
|
}
|
|
|
|
if (!$medium->exists()) {
|
|
abort(404, 'فایل مورد نظر یافت نشد.');
|
|
}
|
|
|
|
$file = $medium->getContents();
|
|
$mimeType = $medium->mime_type;
|
|
|
|
if (!$mimeType) {
|
|
$mimeType = mime_content_type($medium->getStorageDisk()->path($medium->path));
|
|
}
|
|
|
|
return response($file, 200, [
|
|
'Content-Type' => $mimeType,
|
|
'Content-Disposition' => 'inline; filename="' . $medium->filename . '"'
|
|
]);
|
|
}
|
|
|
|
private function generateUniqueFilename(UploadedFile $file): string
|
|
{
|
|
$ext = $file->getClientOriginalExtension();
|
|
$name = Str::slug(pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME));
|
|
return time() . '_' . Str::random(6) . '_' . $name . ($ext ? ".{$ext}" : '');
|
|
}
|
|
}
|