* * * * *
[TOC]
## 簡介
Laravel 提供強大文件抽象能力,這得益于 Frank de Jonge 的?[Flysystem](https://github.com/thephpleague/flysystem)?擴展包。Laravel 集成的 flysystem 提供了可支持本地文件系統、Amazon S3及 Rackspace 云存儲的簡單易用的驅動程序。更棒的是,由于每個系統的API保持不變,所以在這些存儲項之間切換是非常輕松的。
## 配置
文件系統配置文件位于?`config/filesystems.php`。該文件能讓你設置所有的「磁盤(disk)」。每個磁盤代表一個特定的存儲驅動及存儲位置。各種支持驅動的配置示例已包含其中,僅需要簡單的根據你的偏好配置及憑證設置進行修改即可。
當然,你可隨意配置多組磁盤,即使多個磁盤使用相同的驅動。
### 公開磁盤
「公開磁盤」就是指你的文件將可被公開訪問,默認下,?`public`?磁盤使用?`local`?驅動且將文件存放在?`storage/app/public`?目錄下。為了能通過網絡訪問,你需要創建?`public/storage`?到?`storage/app/public`?的符號鏈接。這個約定能讓你的可公開訪問文件保持在同一個目錄下,這樣在不同的部署系統間就可以輕松共享,如?[Envoyer](https://envoyer.io/)的“不停服”部署系統。
你可以使用?`storage:link`?Artisan 命令創建符號鏈接:
~~~
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 安裝適當擴展包:
* Amazon S3:?`league/flysystem-aws-s3-v3 ~1.0`
* Rackspace:?`league/flysystem-rackspace ~1.0`
#### S3 驅動配置
S3 驅動配置信息位于?`config/filesystems.php`?配置文件中。 此文件有個關于S3 驅動的配置數組例子。你可根據自己的 S3 配置和憑證修改該數組。
#### FTP 驅動配置
Laravel 集成的 Flysystem 能很好的支持 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,
],
~~~
#### Rackspace 驅動配置
Laravel 集成的 Flysystem 能很好的支持 Rackspace,不過 Rackspace 的配置示例沒被包含在框架默認的?`filesystems.php`?文件中,需要的話照著下面的例子配置:
~~~
'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',
],
~~~
## 獲得磁盤實例
`Storage`?facade 用于和所有已設置的磁盤交互。例如,你可以調 facade 的?`put`?方法將一張頭像保存到默認磁盤上。調?`Storage`?facade 的方法前若未先調用?`disk`?方法,此方法會被自動傳遞給默認磁盤。
~~~
use Illuminate\Support\Facades\Storage;
Storage::put('avatars/1', $fileContents);
~~~
要是你的應用和多個磁盤交互,你可以通過?`Storage`?facade 的?`disk`?方法訪問特定的磁盤:
~~~
Storage::disk('s3')->put('avatars/1', $fileContents);
~~~
## 提取文件
`get`?方法被用作提取文件內容,此方法返回該文件的原始字符串內容。 切記,所有文件路徑都是基于配置文件中?`root`?目錄的相對路徑。
~~~
$contents = Storage::get('file.jpg');
~~~
`exists`?方法可以被用于判斷一個文件是否存在于磁盤:
~~~
$exists = Storage::disk('s3')->exists('file.jpg');
~~~
### 文件 URLs
當使用?`local`?或者?`s3`?驅動的時候,你可以使用?`url`?方法來獲取給定文件的 URL。如果你使用?`local`?驅動,一般會在傳參的路徑前面加上?`/storage`?且返回相對路徑。如果是?`s3`?的話,返回的是完整的 S3 文件系統的 URL:
~~~
use Illuminate\Support\Facades\Storage;
$url = Storage::url('file1.jpg');
~~~
> {note} 切記,如果使用?`local`?驅動,所有想被公開訪問的文件都應該放在?`storage/app/public`?目錄下。此外,你應該在`public/storage`?[創建符號鏈接 ] (#the-public-disk) 來指向?`storage/app/public`?文件夾。
#### 定制本地 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('file1.jpg');
~~~
`lastModified`?方法返回的最后一次文件被修改的 UNIX 時間戳:
~~~
$time = Storage::lastModified('file1.jpg');
~~~
## 保存文件
`put`?方法用于保存文件原始內容到一個磁盤上。你也可以傳遞 PHP 的?`resource`?給?`put`?方法,它將使用 Flysystem 下的 stream 支持。強烈建議使用 streams 處理大型文件:
~~~
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;
// 自動生成唯一文件名...
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/file1.jpg', 'new/file1.jpg');
Storage::move('old/file1.jpg', 'new/file1.jpg');
~~~
### 文件上傳
在 Web 應用中,存儲文件最常見的例子之一就是存儲用戶上傳的文件,如個人資料圖片,照片和文檔。 Laravel 通過使用文件上傳實例的?`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`?facade 的?`putFile`?方法來執行和上面例子相同的文件操作:
~~~
$path = Storage::putFile('avatars', $request->file('avatar'));
~~~
#### 指定文件名
如果你不喜歡自動生成的文件名,你可以使用?`storeAs`?方法,它接收的路徑、文件名、磁盤(可選的)作為它的參數:
~~~
$path = $request->file('avatar')->storeAs(
'avatars', $request->user()->id
);
~~~
當然,你也可以使用?`Storage`?facade 的?`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(['file1.jpg', 'file2.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 的 Flysystem 集成提供一系列開箱即用的驅動支持;然而 Flysystem 不僅限于此,還擁有其它存儲系統適配器。如果在你的 Laravel 的應用中想使用額外的存儲適配器,你可以創建自定義驅動。
為了建構一個自定義的文件系統,你需要創建一個如?`DropboxServiceProvider`?的?[服務提供者](https://laravel-china.org/docs/laravel/5.4/providers)。并在該提供者的?`boot`?方法使用?`Storage`?facade 的?`extend`?方法自定義你的驅動。
~~~
<?php
namespace App\Providers;
use Storage;
use League\Flysystem\Filesystem;
use Dropbox\Client as DropboxClient;
use Illuminate\Support\ServiceProvider;
use League\Flysystem\Dropbox\DropboxAdapter;
class DropboxServiceProvider extends ServiceProvider
{
/**
* 運行服務注冊后的啟動進程。
*
* @return void
*/
public function boot()
{
Storage::extend('dropbox', function($app, $config) {
$client = new DropboxClient(
$config['accessToken'], $config['clientIdentifier']
);
return new Filesystem(new DropboxAdapter($client));
});
}
/**
* 在容器注冊綁定。
*
* @return void
*/
public function register()
{
//
}
}
~~~
`extend`?方法的第一個參數是驅動名,第二個參數則是一個接受?`$app`?及?`$config`?變量的閉包。該閉包必須返回?`League\Flysystem\Filesystem`?的實例。`$config`?變量包含了在?`config/filesystems.php`?定義的特定磁盤配置。
一旦通過創建服務提供者注冊此擴展后,你就可以在?`config/filesystem.php`?配置文件中使用?`dropbox`?驅動。
- 前言
- 翻譯說明
- 發行說明
- 升級說明
- 貢獻導引
- 入門指南
- 安裝
- 配置信息
- 文件夾結構
- 請求周期
- 開發環境部署
- Homestead
- Valet
- 核心概念
- 服務容器
- 服務提供者
- Facades
- Contracts
- HTTP層
- 路由
- 中間件
- CSRF 保護
- 控制器
- 請求
- 響應
- 視圖
- Session
- 表單驗證
- 前端
- Blade 模板
- 本地化
- 前端指南
- 編輯資源 Mix
- 安全
- 用戶認證
- Passport OAuth 認證
- 用戶授權
- 加密解密
- 哈希
- 重置密碼
- 綜合話題
- Artisan 命令行
- 廣播系統
- 緩存系統
- 集合
- 錯誤與日志
- 事件系統
- 文件存儲
- 輔助函數
- 郵件發送
- 消息通知
- 擴展包開發
- 隊列
- 任務調度
- 數據庫
- 快速入門
- 查詢構造器
- 分頁
- 數據庫遷移
- 數據填充
- Redis
- Eloquent ORM
- 快速入門
- 模型關聯
- Eloquent 集合
- 修改器
- 序列化
- 測試
- 快速入門
- HTTP 測試
- 瀏覽器測試 Dusk
- 數據庫測試
- 測試模擬器
- 官方擴展包
- Cashier 交易工具包
- Envoy 部署工具
- Scout 全文搜索
- Socialite 社會化登錄