今天學習如何處理上傳的圖片
需求是希望 Article 會有一張圖片,所以我們先在 Article Table 上面新增欄位 image 用來存檔案的路徑
Schema::create('articles', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->text('content');
$table->longText('image')->nullable();
$table->integer('category_id');
$table->integer('user_id')->nullable();
$table->timestamps();
});
為了要讓 html form 可以上傳圖片,我們需要在 form tag 上新增使用 enctype attribute,代表上傳資料類型是 multipart/form-data
<form action="{{ route('articles.store') }}" method="POST" enctype="multipart/form-data">// route('string = 在web.php裡定義的route name')<input type="file" name="image">// input type記得是file
在 Controller 中,我們可以在 Request 裡面拿到上傳的檔案 (會被 Laravel 處理成一個 UploadedFile 物件)
我們可以使用 $request->file('image')
取得上傳的檔案,在 UploadedFile 物件有提供 store()
方法,可以直接把檔案存入指定的地方,並且回傳存入的路徑
$path = $request->file('image')->store('images', 'public') // first image 是key,second 是資料夾名稱// config/filesystem.php'disks' => [ 'local' => [ 'driver' => 'local', 'root' => storage_path('app'), ], 'public' => [ 'driver' => 'local', 'root' => storage_path('app/public'), 'url' => env('APP_URL').'/storage', 'visibility' => 'public',
],(default is 'local')$article->image = $path;
$article->save();
檔案實際上會存到 storage/app/public
底下,我們需要下 php artisan storage:link
指令,將這個資料夾變成可透過網址公開存取 (建立捷徑到 public/storage
),public資料夾底下的檔案都可被公開存取,因此才建立捷徑。
最後我們就可以透過 img tag 來顯示圖片
<img src="{{ asset('storage/' . $article->image) }}" />// asset()會提供完整網址
實作完後會發現有兩個問題點:
- 使用者可能沒有上傳檔案
- 上傳新的檔案時,舊的檔案不會被砍掉
對於第一點,我們需要先判斷使用者是否有上傳檔案,如果有上傳檔案的話,我們才做檔案儲存的處理,可以透過 Request 物件的 hasFile
方法來判斷
if ($request->hasFile('image')) {
$path = $request->file('image')->store('images', 'public');
$article->image = $path;
}
對於第二點,我們需要判斷原先的Article是否有圖片,有的話要刪掉,再進行新的檔案儲存處理
// 如果有檔案傳上來
if ($request->hasFile('image')) { // 如果要更新的文章本身原本有圖片,要先刪掉
if ($article->image) {
Storage::disk('public')->delete($article->image);
} // 接著不管原先有無圖片,都會把圖片存入
$path = $request->file('image')->store('images', 'public');;
$article->image = $path;
}
Storage其實是一個抽象的概念,可以儲存在任何地方,Each disk represents a particular storage driver and storage location, ‘public’ 定義在config/filesystem.php,The public
disk is intended for files that are going to be publicly accessible。
Read more: https://laravel.com/docs/5.6/filesystem#configuration