Files
a620906209 a0fa339d6d
Run Tests / test (pull_request) Failing after 11s
docs: 標註 S3 相容儲存尚未啟用(缺 R2 帳號)
在 .env.example 的 AWS_* 區塊與 MigrateStorageToS3 command 加上
TODO(2026-08-03) 註解,說明目前功能已實作但因缺帳號未啟用,直接在
code 裡就看得到狀態,不用另外翻 openspec 文件。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011LpcY9b7y9x4fusHBTXciQ
2026-08-03 03:40:47 +08:00

87 lines
2.8 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use Throwable;
// TODO(2026-08-03): 尚未申請 S3 相容服務帳號,此指令目前無法在正式環境執行
// (會因缺少 AWS_* credentials 連線失敗)。待 R2 帳號建立後才會實際使用,
// 見 openspec/changes/cloud-ready-s3-storage/tasks.md 第 4-6 組。
class MigrateStorageToS3 extends Command
{
protected $signature = 'storage:migrate-to-s3
{--dry-run : 只列出將上傳的檔案與總數,不實際執行}';
protected $description = '將本機 storage/app/public 下既有上傳檔案搬遷至 S3 相容物件儲存(public disk 切換前的一次性遷移,不刪除本機檔案)';
public function handle(): int
{
// 直接指定 local 磁碟為來源,不透過會依 FILESYSTEM_DISK 變動的 'public' disk
// 避免這支指令在 FILESYSTEM_DISK 已切成 s3 後誤把來源當成目的地。
$source = Storage::build([
'driver' => 'local',
'root' => storage_path('app/public'),
]);
$files = $source->allFiles();
if (empty($files)) {
$this->info('storage/app/public 底下沒有檔案,無需遷移。');
return self::SUCCESS;
}
if ($this->option('dry-run')) {
$this->info(sprintf('[dry-run] 將上傳 %d 個檔案:', count($files)));
foreach ($files as $file) {
$this->line(" - {$file}");
}
return self::SUCCESS;
}
$destination = Storage::disk('s3');
$failed = [];
$this->info(sprintf('開始上傳 %d 個檔案至 S3...', count($files)));
$bar = $this->output->createProgressBar(count($files));
foreach ($files as $file) {
try {
$destination->put($file, $source->get($file));
if (! $destination->exists($file)) {
$failed[] = $file;
}
} catch (Throwable $e) {
$failed[] = $file;
$this->newLine();
$this->warn("上傳失敗:{$file}{$e->getMessage()}");
}
$bar->advance();
}
$bar->finish();
$this->newLine(2);
$succeeded = count($files) - count($failed);
$this->info(sprintf('完成:%d/%d 個檔案上傳成功。', $succeeded, count($files)));
if (! empty($failed)) {
$this->error('以下檔案上傳失敗,本機檔案未刪除,可重新執行本指令補上傳:');
foreach ($failed as $file) {
$this->line(" - {$file}");
}
return self::FAILURE;
}
return self::SUCCESS;
}
}