diff --git a/app/Files/TmpFile.php b/app/Files/TmpFile.php index 09dd5f1..a1ae4d0 100644 --- a/app/Files/TmpFile.php +++ b/app/Files/TmpFile.php @@ -2,32 +2,87 @@ namespace App\Files; +use App\Jobs\File\DeleteFile; +use App\Util\DateUtil; +use Illuminate\Contracts\Filesystem\FileNotFoundException; +use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; class TmpFile { - protected const DIR = "/tmp"; + final protected const BASE_DIR = "/tmp"; + + protected const DIR = []; + + + /** + * @param string $id + * @return static + * @throws FileNotFoundException + */ + static public function loadFile(string $id, ...$other): static + { + $file = new static($id, $other); + + if (!$file->exists()) { + throw new FileNotFoundException("ファイルが存在しません:" . $file->getFullPath()); + } + return $file; + } + + protected string $uuid; - public function __construct() + public function __construct(?string $id = null) { - $this->uuid = Str::uuid(); + if ($id === null) { + $this->uuid = Str::uuid(); + } else { + $this->uuid = $id; + } } public function __destruct() { - // ファイルダウンロード前に削除されては困るので処理をコメントアウトしている - // if (Storage::exists($this->getPath())) { - // Storage::delete($this->getPath()); - // } + // 消し忘れ防止のため、削除を予約しておく + if ($this->exists()) { + $lifeTimeMin = config("filesystems.tmpFile.lifetime", 60); + $this->delete(DateUtil::now()->addMinutes($lifeTimeMin)); + } + } + + protected function getFileTypeName() + { + return "tmp"; + } + + protected function getFileExtension(): string + { + return "tmp"; + } + + final protected function getFileName(): string + { + return sprintf("%s_%s.%s", $this->getFileTypeName(), $this->uuid, $this->getFileExtension()); + } + + public function getId(): string + { + return $this->uuid; } public function getPath() { - return static::DIR . "/" . $this->uuid; + return implode( + "/", + [ + self::BASE_DIR, + ...static::DIR + ] + ) . "/" . $this->getFileName(); } public function getFullPath() @@ -40,6 +95,11 @@ class TmpFile Storage::put($this->getPath(), $content); } + public function get() + { + return Storage::get($this->getPath()); + } + public function append(string $content) { Storage::append($this->getPath(), $content); @@ -49,4 +109,22 @@ class TmpFile { return response()->download($this->getFullPath(), $name)->deleteFileAfterSend(); } + + public function exists() + { + return Storage::exists($this->getPath()); + } + + public function delete(?Carbon $delay = null): void + { + if ($delay === null) { + $ret = Storage::delete($this->getPath()); + if ($ret) info(sprintf("ファイル削除:%s ", $this->getFullPath())); + return; + } else { + DeleteFile::dispatch($this) + ->delay($delay); + return; + } + } } diff --git a/app/Jobs/File/DeleteFile.php b/app/Jobs/File/DeleteFile.php new file mode 100644 index 0000000..9bddabd --- /dev/null +++ b/app/Jobs/File/DeleteFile.php @@ -0,0 +1,47 @@ +onQueue(QueueName::JOB->value); + $this->fileId = $file->getId(); + $this->storagePath = $file->getPath(); + logger("FILE削除JOB登録:" . $this->storagePath); + } + + /** + * Execute the job. + * + * @return void + */ + public function handle() + { + if (Storage::exists($this->storagePath)) { + Storage::delete($this->storagePath); + info(sprintf("ファイル削除:%s ", $this->storagePath)); + } + } +} diff --git a/config/filesystems.php b/config/filesystems.php index e9d9dbd..12660e0 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -39,7 +39,7 @@ return [ 'public' => [ 'driver' => 'local', 'root' => storage_path('app/public'), - 'url' => env('APP_URL').'/storage', + 'url' => env('APP_URL') . '/storage', 'visibility' => 'public', 'throw' => false, ], @@ -73,4 +73,16 @@ return [ public_path('storage') => storage_path('app/public'), ], + /* + |-------------------------------------------------------------------------- + | 一時ファイル設定 + |-------------------------------------------------------------------------- + | + | + */ + + 'tmpFile' => [ + 'lifetime' => env('TMP_FILE_LIFETIME_MIN', 60), // 分 + ] + ];