引言
如果我們的應用程式接收使用者提交的許多靜態檔案,文件,圖片等等,需要將其上傳到伺服器並進行有效地管理。
然而,檔案型別繁多,檔案用途不同;還有可能我們使用第三方的物件儲存服務,需要像訪問本地檔案一樣地讀取遠端的檔案。
如果有一套統一的API,或者操作風格,那樣會節省很多不必要的差異化程式碼。laravel提供的Storage文件儲存管理正式因此產生的,本期我們就來說一說。
程式碼時間首先在配置檔案內宣告各個磁碟配置,可以設定驅動,配置目錄等差異化資訊。 在 config/filesystem.php 檔案內新增如下配置程式碼:
'disks' => [ 'local' => [ 'driver' => 'local', 'root' => storage_path('app'), ], 'public' => [ 'driver' => 'local', 'root' => storage_path('app/public'), 'visibility' => 'public', ], 's3' => [ 'driver' => 's3', 'key' => 'your-key', 'secret' => 'your-secret', 'region' => 'your-region', 'bucket' => 'your-bucket', ],],
其中 driver 為 local 時,表示本地的檔案系統驅動。
如果要把 storage 目錄下的公用目錄 public 公開到網路可訪問位置, 我們為其建立一個軟連線:
php artisan storage:link
這樣就把目錄 public 指向了 storage/app/public 目錄。那麼位於該目錄下的所有檔案, 可通過web伺服器的根目錄直接訪問。
檔案操作laravel提供的Storage檔案操作類,封裝了非常方便的檔案讀寫和高階的功能操作。 比如讀取一個檔案的內容:
Storage::disk('s3')->get('file.jpg');
上述程式碼,讀取s3服務上的一個圖片檔案。
覆蓋性寫入一個檔案,或者建立一個新的不存在的檔案,使用 put 方式:
Storage::disk('local')->put('file.jpg', $contentsOrStream)
或者把上傳的檔案,直接放入到某個指定的目錄:
Storage::putFile('myDir', $file)
其中 $file 是一個 Illuminate\\Http\\File or Illuminate\\Http\\UploadedFile 物件的例項。 我們通過表單上傳的file欄位檔案,可以使用
request()->file('file_field')
方便地獲取。還有常用的判斷檔案是否存在:
Storage::exists('file.jpg')
避免了我們寫 file_exists 這樣還有傳入絕對路徑,或者相對路徑的麻煩,使用物件方法操作, 使得程式碼風格更為統一。
還有常用的一些方法,我們不一一解釋了,羅列在下方:
檔案複製 copy('file.jpg', 'newfile.jpg')檔案重新命名 move('file.jpg', 'newfile.jpg')檔案頭部追加內容 prepend('my.log', 'log text')檔案尾部追加內容 append('my.log', 'log text')刪除檔案 delete('file.jpg')等等等等,讀者可以自定檢視文件或在原始碼中研讀。
如果我們引入了一個第三方的檔案儲存服務,且有其一套API操作方式, 而laravel系統並未提供該服務的驅動,能否自定義一套呢?完全可以。
框架的檔案系統驅動使用了 Flysystem 庫用於統一化管理。我們只需要 擴充套件Storage,並將第三方的驅動API實現Storage介面方法即可在程式內無差別地使用了。
在 AppServiceProvider 的 boot 方法內實現該擴充套件。比如我們引入 dropbox 儲存服務:
Storage::extend('dropbox', function ($app, $config) { $client = new DropboxClient( $config['accessToken'], $config['clientIdentifier'] ); return new Filesystem(new DropboxAdapter($client));});
我們使用Dropbox公司提供的 PHP SDK,或者使用composer安裝相關包,在擴充套件方法中註冊該驅動引擎即可。
寫在最後本文初步介紹了laravel中是如何使用Storage物件無差別地執行檔案操作, 使用者只需關注檔案操作邏輯,而不用在意底層的驅動方式,這樣非常便於統一化。 最後簡介了引入自定義檔案驅動的方法。
Happy coding :-)