Laravel Note 7 — File Storage

Luna Wang
5 min readMar 7, 2018

--

今天學習如何處理上傳的圖片

需求是希望 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()會提供完整網址

實作完後會發現有兩個問題點:

  1. 使用者可能沒有上傳檔案
  2. 上傳新的檔案時,舊的檔案不會被砍掉

對於第一點,我們需要先判斷使用者是否有上傳檔案,如果有上傳檔案的話,我們才做檔案儲存的處理,可以透過 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

--

--