檔案系統與雲端儲存

簡介

Laravel 強大的檔案抽象層得力於 Frank de Jonge 的 Flysystem 套件。Laravel 的 flysystem 整合以各種驅動(driver)提供本地端磁碟系統、Amazon S3、以及 Rackspace 雲端儲存。並且能像使用 API 一般,輕易的切換這些儲存方式來面對各式系統。

設定

檔案系統設定檔位於 config/filesystems.php。該檔案能讓你設定所有的「磁碟(disk)」。每個磁碟代表一種獨特的儲存驅動以及儲存位置。各種支援驅動範例已包含在其中,僅需要簡單的根據你的偏好配置及憑證設定進行變更即可。

當然,你可以設定多組磁碟,甚至使用相同驅動。

本地端驅動

當使用 local 驅動,所有的操作是相對於設定檔中的 root 目錄設定進行。該目錄預設是 storage/app。因此下列方法將把檔案儲存在 storage/app/file.txt

Storage::disk('local')->put('file.txt', 'Contents');

其他驅動的預先需求

在使用 S3 或 Rackspace 驅動之前,你需要透過 Composer 安裝適當套件:

基本用法

獲得磁碟實體

Storage facade 用於對任何已設定的磁碟進行互動。舉例來說,你可以使用 facade 的 put 方法將一張頭像儲存到預設磁碟。當使用 Storage facade 呼叫任一方法而未先呼叫 disk 方法,預設磁碟將自動傳遞給該方法。

<?php

namespace App\Http\Controllers;

use Storage;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
    /**
     * Update the 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 facade 的 disk 方法存取特定磁碟。當然,你也可以使用方法鏈結(chain methods)對磁碟使用各種執行方法。

$disk = Storage::disk('s3');

$contents = Storage::disk('local')->get('file.jpg')

提取檔案

get 方法提取給定檔案的內容,該檔案的原始字串內容將透過該方法取得:

$contents = Storage::get('file.jpg');

has 方法可以用於判定給定的檔案是否存於磁碟上:

$exists = Storage::disk('s3')->has('file.jpg');

檔案資訊

size 方法取得檔案的大小並以 bytes 顯示:

$size = Storage::size('file1.jpg');

lastModified 方法回傳檔案的最後修改時間並以 UNIX 時間戳記顯示:

$time = Storage::lastModified('file1.jpg');

儲存檔案

put 方法儲存單一檔案於磁碟上。你能同時傳遞 PHP 的 resourceput 方法,它將使用檔案系統底層的 stream 支援。強烈建議使用 stream 處理大型檔案。

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');

插入到檔案

prependappend 方法允許你輕易的插入內容到一個檔案的開頭或結尾:

Storage::prepend('file.log', 'Prepended Text');

Storage::append('file.log', 'Appended Text');

刪除檔案

delete 方法接受一個檔案名稱或檔案名稱陣列,用以移除磁碟上的檔案:

Storage::delete('file.jpg');

Storage::delete(['file1.jpg', 'file2.jpg']);

目錄

取得單一目錄內所有檔案

files 方法回傳給定目錄下的檔案陣列。如果你希望回傳包含給定目錄下所有子目錄的檔案,你可以使用 allFiles 方法。

$files = 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 整合的 Flysystem 提供許多預設的驅動;然而 Flysystem 本身提供了不僅僅這些,還包括其他儲存系統的接口(adapter)。你能在 Laravel 的應用當中通過建立新的驅動使用這些額外的接口。

為了建構一個自訂的磁碟系統,你將需要建立一個像是 DropboxServiceProvider服務提供者。並在該提供者的 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
{
    /**
     * 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 驅動。