* * * * *
[TOC]
## 簡介
Laravel 提供了一個強大的文件系統抽象,這得益于 Frank de Jonge 強大的?[Flysystem](https://github.com/thephpleague/flysystem)?擴展包。Laravel 文件系統集成為使用本地文件系統、Amazon S3 和 Rackspace 云存儲提供了簡單易用的驅動程序。更棒的是,由于每個系統的 API 保持不變,所以在這些存儲選項之間切換是非常簡單的。
## 配置
文件系統的配置文件位于?`config/filesystems.php`?。在這個文件中你可以配置所有「磁盤」。每個磁盤代表特定的存儲驅動及存儲位置。每種支持的驅動程序的示例配置都包含在配置文件中。因此,只需要修改配置即可反映你的存儲偏好和憑據。
當然,你可以根據需要配置多個磁盤,甚至你還可以使多個磁盤共用同一個驅動。
### 公共磁盤
`public`?磁盤適用于要公開訪問的文件。默認情況下,?`public`?磁盤使用?`local`?驅動,并且將這些文件存儲在?`storage/app/public`?目錄下。為了使它們能通過網絡訪問,你需要創建?`public/storage`?到`storage/app/public`?的符號鏈接。這種方式能把可公開訪問文件都保留在同一個目錄下,以便在使用零停機時間部署系統如?[Envoyer](https://envoyer.io/)?的時候,就可以輕松地在不同的部署之間共享這些文件。
你可以使用 Artisan 命令?`storage:link`?來創建符號鏈接:
~~~
php artisan storage:link
~~~
當然,一旦一個文件被存儲并且已經創建了符號鏈接,你就可以使用輔助函數?`asset`?來創建文件的 URL:
~~~
echo asset('storage/file.txt');
~~~
### 本地驅動
使用?`local`?驅動時,所有文件操作都與你在配置文件中定義的?`root`?目錄相關。該目錄的默認值是?`storage/app`。因此,以下方法會把文件存儲在?`storage/app/file.txt`?中:
~~~
Storage::disk('local')->put('file.txt', 'Contents');
~~~
### 驅動程序先決條件
#### Composer 包
在使用 S3 或 Rackspace 的驅動之前,你需要通過 Composer 安裝相應的軟件包:
* SFTP:?`league/flysystem-sftp ~1.0`
* Amazon S3:?`league/flysystem-aws-s3-v3 ~1.0`
* Rackspace:?`league/flysystem-rackspace ~1.0`
#### S3 驅動配置
S3 驅動配置信息位于你的?`config / filesystems.php`?配置文件中。 該文件包含 S3 驅動程序的示例配置數組。 你可以自由使用你自己的 S3配置和憑證修改此陣列。 為方便起見,這些環境變量與 AWS CLI 使用的命名約定相匹配。
#### FTP 驅動配置
Laravel 的文件系統集成能很好的支持 FTP,不過 FTP 的配置示例并沒有被包含在框架默認的?`filesystems.php`?文件中。需要的話可以使用下面的示例配置:
~~~
'ftp' => [
'driver' => 'ftp',
'host' => 'ftp.example.com',
'username' => 'your-username',
'password' => 'your-password',
// Optional FTP Settings...
// 'port' => 21,
// 'root' => '',
// 'passive' => true,
// 'ssl' => true,
// 'timeout' => 30,
],
~~~
#### SFTP 驅動器的配置
Laravel 的 Flysystem 集成包與 SFTP 協同得非常好;不過,在該框架的默認配置文件?`filesystems.php`?中并沒有包含示范配置。如果要配置 SFTP 文件系統,可以使用如下示例配置:
~~~
'sftp' => [
'driver' => 'sftp',
'host' => 'example.com',
'username' => 'your-username',
'password' => 'your-password',
// 基于認證的 SSH key 設置...
// 'privateKey' => '/path/to/privateKey',
// 'password' => 'encryption-password',
// 可選的 SFTP 設置...
// 'port' => 22,
// 'root' => '',
// 'timeout' => 30,
],
~~~
#### Rackspace 驅動器的配置
Laravel 的 Flysystem 集成包與 Rackspace 協同得非常好;不過,在該框架的默認配置文件?`filesystems.php`?中并沒有包含示范配置。如果要配置 Rackspace 文件系統,可以使用如下示例配置:
~~~
'rackspace' => [
'driver' => 'rackspace',
'username' => 'your-username',
'key' => 'your-key',
'container' => 'your-container',
'endpoint' => 'https://identity.api.rackspacecloud.com/v2.0/',
'region' => 'IAD',
'url_type' => 'publicURL',
],
~~~
## 獲取 Disk 實例
facade 方式?`Storage`?可以用于與任何已配置磁盤互操作。例如該 facade 方式可以使用?`put`?方法存儲頭像到默認磁盤。如果調用 facade 方式?`Storage`?方法,并且一開始沒有調用?`disk`?方法,那么所調用的方法會自動傳遞給默認的磁盤:
~~~
use Illuminate\Support\Facades\Storage;
Storage::put('avatars/1', $fileContents);
~~~
如果應用程序要與多個磁盤進行互操作,可使用 facade 方式?`Storage`?中的?`disk`?方法,對特定磁盤上的多個文件進行操作:
~~~
Storage::disk('s3')->put('avatars/1', $fileContents);
~~~
## 檢索文件
`get`?方法可以用于檢索文件的內容,此方法返回該文件的原始字符串內容。 切記,所有文件路徑的指定都應該相對于為磁盤配置的?`root`?目錄:
~~~
$contents = Storage::get('file.jpg');
~~~
`exists`?方法可以用來判斷磁盤上是否存在指定的文件:
~~~
$exists = Storage::disk('s3')->exists('file.jpg');
~~~
### 下載文件
`download`?方法可用于生成一個響應,強制用戶的瀏覽器在給定路徑下載文件。?`download`?方法接受一個文件名作為方法的第二個參數,它將確定用戶下載文件時看到的文件名。 最后,你可以傳遞一個 HTTP 頭數組作為該方法的第三個參數:
~~~
return Storage::download('file.jpg');
return Storage::download('file.jpg', $name, $headers);
~~~
### 文件 URLs
當使用?`local`?或者?`s3`?驅動時,你可以使用?`url`?方法來獲取給定文件的 URL。如果你使用的是?`local`?驅動,一般只是在給定的路徑前面加上?`/storage`?并返回一個相對的 URL 到那個文件。如果使用的是?`s3`?驅動,會返回完整的遠程 URL:
~~~
use Illuminate\Support\Facades\Storage;
$url = Storage::url('file.jpg');
~~~
> {note} 切記,如果使用的是?`local`?驅動,則所有想被公開訪問的文件都應該放在?`storage/app/public`?目錄下。此外,你應該在?`public/storage`?[創建一個符號鏈接?](http://www.hmoore.net/tonyyu/laravel_5_6/786243#_12)來指向?`storage/app/public`?目錄。
#### 臨時 URLs
對于使用?`s3`?驅動來存儲的文件,可以使用?`temporaryUrl`?方法創建給定文件的臨時 URL 。這個方法接收路徑和?`DateTime`?實例來指定 URL 何時過期:
~~~
$url = Storage::temporaryUrl(
'file.jpg', now()->addMinutes(5)
);
~~~
#### 自定義本地 URL 主機
如果要使用?`local`?驅動為存儲在磁盤上的文件預定義主機,可以向磁盤配置數組添加一個?`url`?選項:
~~~
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
~~~
### 文件元數據
除了讀寫文件,Laravel 還可以提供有關文件本身的信息。例如,`size`?方法可用來獲取文件的大小(以字節為單位):
~~~
use Illuminate\Support\Facades\Storage;
$size = Storage::size('file.jpg');
~~~
`lastModified`?方法返回最后一次文件被修改的 UNIX 時間戳:
~~~
$time = Storage::lastModified('file.jpg');
~~~
## 保存文件
`put`?方法可用于將原始文件內容保存到磁盤上。你也可以傳遞 PHP 的?`resource`?給?`put`?方法,它將使用文件系統下的底層流支持。強烈建議在處理大文件時使用流:
~~~
use Illuminate\Support\Facades\Storage;
Storage::put('file.jpg', $contents);
Storage::put('file.jpg', $resource);
~~~
#### 自動流式傳輸
如果你想 Laravel 自動管理將給定文件流式傳輸到你想要的存儲位置,你可以使用?`putFile`?或?`putFileAs`?方法。這個方法接受?`Illuminate\HTTP\File`?或?`Illuminate\HTTP\UploadedFile`?實例,并自動將文件流式傳輸到你想要的位置:
~~~
use Illuminate\Http\File;
use Illuminate\Support\Facades\Storage;
// 自動為文件名生成唯一的 ID...
Storage::putFile('photos', new File('/path/to/photo'));
// 手動指定文件名...
Storage::putFileAs('photos', new File('/path/to/photo'), 'photo.jpg');
~~~
關于?`putFile`?方法有些重要的事情要注意。請注意,我們只指定一個目錄名,而不是文件名。默認情況下,`putFile`?方法將生成唯一的 ID 作為文件名。該文件的路徑將被?`putFile`?方法返回,因此可以將路徑(包括生成的文件名)存儲在數據庫中。
`putFile`?和?`putFileAs`?方法也接受一個參數來指定存儲文件的「可見性」。如果你將文件存儲在諸如 S3 的云盤上,并且該文件可以公開訪問,這是特別有用的:
~~~
Storage::putFile('photos', new File('/path/to/photo'), 'public');
~~~
#### 文件數據寫入
`prepend`?和?`append`?方法可以在文件的頭部或尾部寫入數據:
~~~
Storage::prepend('file.log', 'Prepended Text');
Storage::append('file.log', 'Appended Text');
~~~
#### 復制 & 移動文件
`copy`?方法可以復制文件到新地址,`move`?方法可以重命名文件或移動文件到新地址:
~~~
Storage::copy('old/file.jpg', 'new/file.jpg');
Storage::move('old/file.jpg', 'new/file.jpg');
~~~
### 文件上傳
Web 應用中,常用到文件存儲的地方也就是上傳頭像、照片、文件等。Lavarel 上傳文件實例的?`store`?方法可以輕松處理文件上傳存儲的問題。`store`?方法接受一個目錄:
~~~
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class UserAvatarController extends Controller
{
/**
* 更新用戶頭像
*
* @param Request $request
* @return Response
*/
public function update(Request $request)
{
$path = $request->file('avatar')->store('avatars');
return $path;
}
}
~~~
上例需要注意幾個問題。這里指定的是目錄名,而不是文件名。默認情況下,`store`?方法自動生成唯一的 ID 作為文件名。`store`?方法返回包含文件名的路徑,以便后續的數據庫存儲。
`Storage`?門面的?`putFile`?方法可以達到上面同樣的操作效果:
~~~
$path = Storage::putFile('avatars', $request->file('avatar'));
~~~
#### 自定義文件名
不想自動生成文件名的話,可以使用?`storeAs`?方法,它接受路徑、文件名和可選的磁盤三個參數:
~~~
$path = $request->file('avatar')->storeAs(
'avatars', $request->user()->id
);
~~~
`Storage`?門面的?`putFileAs`?方法也可以達到上面的操作效果:
~~~
$path = Storage::putFileAs(
'avatars', $request->file('avatar'), $request->user()->id
);
~~~
#### 自定義磁盤
默認情況下,`store`?方法使用默認磁盤,如果想使用其它磁盤,可以給它傳入磁盤名作為第二個參數:
~~~
$path = $request->file('avatar')->store(
'avatars/'.$request->user()->id, 's3'
);
~~~
### 文件可見性
Laravel 集成的 Flysystem 系統,對多平臺的文件權限進行了「可見性」抽象。文件可聲明為?`public`?或?`private`。通常,一個聲明成?`public`?的文件,意味著對其他人可訪問。例如,使用 S3 驅動時,就可以檢索聲明為?`public`?文件的 URL。
`put`?方法可以設置文件的可見性:
~~~
use Illuminate\Support\Facades\Storage;
Storage::put('file.jpg', $contents, 'public');
~~~
`getVisibility`?和?`setVisibility`?方法可以對現存文件進行可見性的檢查和設置:
~~~
$visibility = Storage::getVisibility('file.jpg');
Storage::setVisibility('file.jpg', 'public')
~~~
## 刪除文件
`delete`?方法接受單個文件名或數組形式的文件名來刪除磁盤上的文件:
~~~
use Illuminate\Support\Facades\Storage;
Storage::delete('file.jpg');
Storage::delete(['file.jpg', 'file2.jpg']);
~~~
必要的話,可以指定磁盤名來刪除其下的文件:
~~~
use Illuminate\Support\Facades\Storage;
Storage::disk('s3')->delete('folder_path/file_name.jpg');
~~~
## 目錄
#### 獲取目錄下所有文件
`files`?方法返回指定目錄下的所有文件的數組。`allFiles`?方法返回指定目錄下包含子目錄的所有文件的數組:
~~~
use Illuminate\Support\Facades\Storage;
$files = Storage::files($directory);
$files = Storage::allFiles($directory);
~~~
#### 獲取目錄下所有的目錄
`directories`?方法返回給定目錄下的所有目錄的數組。`allDirectories`?方法返回指定目錄下的包含子目錄的所有目錄的數組:
~~~
$directories = Storage::directories($directory);
// 遞歸
$directories = Storage::allDirectories($directory);
~~~
#### 創建目錄
`makeDirectory`?方法會遞歸創建目錄:
~~~
Storage::makeDirectory($directory);
~~~
#### 刪除目錄
`deleteDirectory`?方法會刪除指定目錄及其所有文件:
~~~
Storage::deleteDirectory($directory);
~~~
## 自定義文件系統
雖然 Laravel 的 文件系統提供了一系列開箱即用的驅動,但是它不限于這些,還提供了其他存儲系統的適配器。通過這些適配器,可以在 Lavarel 應用中創建自定義驅動。
為了配置自定義文件系統,現在把社區維護的 Dropbox 適配器添加到項目中:
~~~
composer require spatie/flysystem-dropbox
~~~
接下來,創建一個名為?`DropboxServiceProvider`?的?[服務提供器](http://www.hmoore.net/tonyyu/laravel_5_6/786057)。在它的?`boot`?方法里,用?`Storage`?門面的?`extend`?自定義驅動:
~~~
<?php
namespace App\Providers;
use Storage;
use League\Flysystem\Filesystem;
use Illuminate\Support\ServiceProvider;
use Spatie\Dropbox\Client as DropboxClient;
use Spatie\FlysystemDropbox\DropboxAdapter;
class DropboxServiceProvider extends ServiceProvider
{
/**
* 執行注冊后引導服務
*
* @return void
*/
public function boot()
{
Storage::extend('dropbox', function ($app, $config) {
$client = new DropboxClient(
$config['authorizationToken']
);
return new Filesystem(new DropboxAdapter($client));
});
}
/**
* 在容器中注冊綁定
*
* @return void
*/
public function register()
{
//
}
}
~~~
`extend`?方法的第一個參數是驅動的名稱,第二個參數是個閉包,接受?`$app`?和?`$config`?兩個變量。這個閉包必須返回?`League\Flysystem\Filesystem`?的實例。`$config`?變量包含了指定磁盤在?`config/filesystems.php`?中的配置。
注冊好擴展后, 就可以通過配置?`config/filesystems.php`?使用`dropbox`?了。
- 前言
- 翻譯說明
- 發行說明
- 升級指南
- 貢獻導引
- 入門指南
- 安裝
- 配置信息
- 文件夾結構
- Homestead
- Valet
- 部署
- 核心架構
- 請求周期
- 服務容器
- 服務提供者
- Facades
- Contracts
- 基礎功能
- 路由
- 中間件
- CSRF 保護
- 控制器
- 請求
- 響應
- 視圖
- URL
- Session
- 表單驗證
- 錯誤
- 日志
- 前端開發
- Blade 模板
- 本地化
- 前端指南
- 編輯資源 Mix
- 安全相關
- 用戶認證
- Passport OAuth 認證
- 用戶授權
- 加密解密
- 哈希
- 重置密碼
- 綜合話題
- Artisan 命令行
- 廣播系統
- 緩存系統
- 集合
- 事件系統
- 文件存儲
- 輔助函數
- 郵件發送
- 消息通知
- 擴展包開發
- 隊列
- 任務調度
- 數據庫
- 快速入門
- 查詢構造器
- 分頁
- 數據庫遷移
- 數據填充
- Redis
- Eloquent ORM
- 快速入門
- 模型關聯
- Eloquent 集合
- 修改器
- API 資源
- 序列化
- 測試相關
- 快速入門
- HTTP 測試
- 瀏覽器測試 Dusk
- 數據庫測試
- 測試模擬器
- 官方擴展包
- Cashier 交易工具包
- Envoy 部署工具
- Horizon
- Scout 全文搜索
- Socialite 社會化登錄