文件系統/云存儲
簡介
laravel 提供了一個強大的文件系統的抽象,這得益于 Frank de Jonge 所開發的 Flyststem PHP 包。laravel 的文件系統提供了對一些存儲驅動的支持,它們包括本地文件系統,Amazon S3,Rackspace 云存儲。更為奇妙的是,它可以通過存儲配置選項來切換這些存儲系統,因為 laravel 對它們提供了統一的 API 接口。
配置
文件系統的配置選項存儲在 config/filesystems.php
文件中。在這個文件中你可以對所有的磁盤進行配置。每個磁盤選項包含著其所使用的存儲驅動及其存儲位置。對于 laravel 默認支持的存儲驅動,在這個文件中都有相應的配置示例。所以,你可以簡單的在這個文件中修改配置選項就可以使用其強大的功能。
當然,你可以配置多個磁盤,甚至可以使多個磁盤使用相同的驅動。
公共磁盤
public
磁盤意味著其可以被公開的訪問。默認的 public
磁盤使用的是 local
驅動并且其存儲的文件位置是在 storage/app/public
目錄。如果你想要這個目錄下的文件可以在 web 中進行訪問,你需要創建一個 public/storage
到 storage/app/public
的符號鏈接。這個約定可以使公開訪問的文件保持存放在同一個目錄中并且可以在使用像 Envoyer 這種無痛持續部署系統時可以方便的共享整個部署過程。
當然,一旦文件被存儲并且建立了符號鏈接。你就可以通過 asset
幫助方法來生成文件的 URL:
echo asset('storage/file.txt')
本地驅動
當使用 local
驅動時,你需要知道的是所有的文件操作都是相對于配置文件中的 root
選項所定義的目錄。默認的這個值設置的是 storage/app
目錄。因此,下面的方法將文件存儲到 storage/app/file.txt
:
Storage::disk('local')->put('file.txt', 'Contents');
其他驅動先決條件
在使用 S3 或者 Rackspace 驅動之前,你需要先通過 Composer 來安裝適當的包文件:
- Amazon S3:
league/flysystem-aws-s3-v3 ~1.0
- Rackspace:
league/flysystem-rackspace ~1.0
FTP 驅動配置
laravel 的文件系統可以很好的支持 FTP 的集成,但是在默認的配置文件中并沒有給出示例。如果你需要配置 FTP 的文件系統,你可以使用下面的配置示例:
'ftp' => [
'dirver' => '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 的文件系統可以很好的支持 Rackspace 的集成,但是在默認的配置文件中并沒有給出示例。如果你需要配置 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',
],
基礎用法
獲取磁盤實例
Storage
假面可以用來和你所配置的磁盤進行交互。比如,你可以使用它的 put
方法來將用戶的頭像圖片存儲到默認的磁盤。如果你在調用該方法的時候沒有在其之前使用 disk
方法的話,那么該方法會自動的將頭像傳遞到默認的磁盤:
<?php
namespace App\Http\Controllers;
use Storage;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* Update teh avatar for the given user.
*
* @param Request $request
* @param int $id
* @return Response
*/
public function updateAvatar(Request $request, $id)
{
$user = User::findOrFail($id);
Storage::put(
'avatars/'.$user->id,
file_get_contents($request->file('avatar')->getRealPath())
);
}
}
當你使用多個磁盤時,你可以使用 Storage
假面的 disk
方法來指定訪問的磁盤。當然,你可以使用鏈式的方法來進行持續的操作:
$disk = Storage::disk('s3');
$contents = Storage::disk('local')->get('file.jpg');
檢索文件
get
方法可以用來從所給定的文件中檢索出其內容。該方法會返回文件的原始字符串內容:
$contents = Storage::get('file.jpg');
exists
方法可以用來判斷所給定的文件是否存在于磁盤中:
$exists = Storage::disk('s3')->exists('file.jpg');
文件 URLs
當使用 local
或者 s3
驅動時,你可以使用 url
方法來獲得給定文件的 URL。如果你使用的是 local
驅動,那它只會簡單的在給定的路徑前增加 /storage
前綴以返回相對的文件路徑。如果你使用的是 s3
驅動,將會返回完整的遠端 RUL:
$url = Storage::url('file1.jpg');
注意:當使用的是
local
驅動時,一定要確保創建了public/storage
到storage/app/public
的符號鏈接。
文件元信息
size
方法可以用來獲取給定文件的字節大小:
$size = Storage::size('file1.jpg');
lastModified
方法會返回給定文件的最后修改時間,它使用的 是 UNIX 時間戳:
$time = Storage::lastModified('file1.jpg');
存儲文件
put
方法可以用來將文件存儲到磁盤。你可以傳遞一個 PHP 的 resource
到 put
方法,那么它會使用文件系統的底層流支持。在與大型文件交互時,推薦使用文件流:
Storage::put('file.jpg', $contents);
Storage::put('file.jpg', $resource);
copy
方法可以用來復制磁盤中已存在的文件到新的位置:
Storage::copy('old/file1.jpg', 'new/file1.jpg');
move
方法可以被用對磁盤中已存在的文件進行名稱的修改或移動到新的位置:
Storage:move('old,file1.jpg', 'new/file1.jpg');
前置或追加內容到文件
prepend
和 append
方法允許你輕松的往文件的起始或結束位置加入內容:
Storage::prepend('file.log', 'Prepended Text');
Storage::append('file.log', 'Appended Text');
文件可見性
你可以通過使用 getVisibility
和 setVisibility
方法來進行文件可見性的檢索和設置。可見性是跨平臺的文件權限的抽象:
Storage::getVisibility('file.jpg');
Storage::setVisibility('file.jpg', 'public');
另外,你可以在使用 put
方法的同時設置文件的可見性。有效的可見性值是 public
和 private
:
Storage::put('file.jpg', $contents, 'public');
刪除文件
delete
方法可以接受一個文件名或者文件名所組成的數組,它將從磁盤中刪除相應的文件:
Storage::delete('file.jpg');
Storage::delete(['file1.jpg', 'file2.jpg']);
目錄
從目錄中獲取所有文件
files
方法會返回所給定目錄中所有的文件所組成的數組。如果你想要在檢索到的文件中包含所給定目錄的子目錄。那么你需要使用 allFiles
方法:
$file = Storage::files($directory);
$files = Storage::allFiles($directory);
從給定的目錄中獲取所有的目錄
directories
方法可以返回所給定目錄下的所有子目錄所組成的數組。另外你可以使用 allDirectories
方法遞歸檢索子目錄:
$directories = Storage::directories($directory);
// Recursive...
$directories = Storage::allDirectories($directory);
創建目錄
makeDirectory
方法將創建給定的目錄,包括其所需要的子目錄:
Storage::makeDirectory($directory);
刪除一個目錄
最后,deleteDirectory
方法可以用來刪除一個目錄,并且其刪除磁盤中該目錄下所有的文件:
Storage::deleteDirectory($directory);
自定義文件系統
laravel 的文件系統對幾種常見的存儲系統提供了開箱即用的支持。事實上,文件系統并沒有限制你只使用所提供的這些。你可以自己創建一個適配器來構建一個自定義的驅動去支持你所期望使用的文件存儲系統。
你需要創建一個服務提供者來進行自定義文件存儲系統的構建。比如 DropboxServiceProvider
。在提供者的 boot
方法中,你需要使用 Storage
假面的 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
{
/**
* Perform post-registration booting of services.
*
* @return void
*/
public function boot()
{
Storage::extend('dropbox', function ($app, $config) {
$client = new DropboxClient(
$config['accessToken'], $config['clientIdentifier']
);
return new Filesystem(new DropboxAdapter($client));
});
}
/**
* Register bindings in the container.
*
* @return void
*/
public function register()
{
//
}
}
extend
方法中的第一個參數應該是驅動的名稱,第二個參數是一個閉包,閉包接受 $app
和 $config
變量。被解析的閉包必須返回一個 League\Flysystem\Filesystem
的實例。$config
變量包含了 config/filesystems.php
文件中指定磁盤的值。
一旦你創建了服務提供者并且注冊了這個擴展,你就可以在 config/filesystem.php
配置文件中使用 dropbox
驅動了。