Filesystem / Cloud Storage

Giới thiệu

Laravel cung cấp một lớp abstraction cho filesystem khá mạnh mẽ nhờ có sử dụng tới PHP package tuyệt vời Flysystem của Frank de Jonge. Việc tích hợp Flysystem vào Laravel cung cấp cách sử dụng rất đơn giản để giao tiếp với các local filesystem, Amazon S3, và Rackspace Cloud Storage. Thậm chí còn hay hơn, đó là có thể thay đổi các storage này cực kì dễ dàng mà sử dụng chung API cho các hệ thống.

Cấu hình

File cấu hình cho filesystem được đặt tại config/filesystems.php. Trong file này, bạn có thể cấu hình tất cả "disks" của bạn. Mỗi diesk tượng trưng cho một storage driver cụ thể và vị trí storage. Cấu hình ví dụ cho mỗi driver nằm trong file cấu hình. Vì thế, hãy thay đổi giá trị cấu hình sao cho hợp với ý của bạn.

Tất nhiên, bạn có thể cấu hình bao nhiêu disk tuỳ thích, và thậm chí có thể sử dụng nhiều disks mà cùng sử dụng chung driver.

The Public Disk

Disk public dùng cho các files có thể được truy cập công khai từ bên ngoài. Mặc định public disk sử dụng local driver và lưu tại storage/app/public. Để chúng có thể truy cập từ web, bạn nên tạo một symbolic link từ public/storage vào storage/app/public. Cách này sẽ làm cho các file public trong một thư mục mà có thể dễ dàng chia sẻ qua các lần triển khai khi sử dụng hệ thống triển khai không mất thời gian như Envoyer.

Để tạo symbolic link, bạn có thể sử dụng lệnh storage:link:

php artisan storage:link

Dĩ nhiên, khi mà file đã được lưu và symbolic link được tạo, bạn có thể tạo một URL tới file sử dụng hàm helper asset

echo asset('storage/file.txt');

The Local Driver

Khi sử dụng local driver, chú ý là tất cả các thao tác tới file là relative tới thư mục root mà được khai báo trong file cấu hình. Về mặc định, giá trị này được trỏ tới thư mục storage/app. Vì thế, hàm sau đây sẽ lưu file vào trong storage/app/file.txt:

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

Các yêu cầu driver khác

Composer Packages

Trước khi sử dụng S3 hay Rackspace drivers, bạn sẽ cần cài đặt các package phù hợp thông qua Composer:

Cấu hình S3 Driver

Thông tin cấu hình S3 driver nằm tại file config/filesystems.php . File này chứa một mảng ví dụ cấu hình cho một S3 driver. Bạn có thể thoải mái tùy chỉnh mảng này phù hợp với thông tin S3 của bạn.

Cấu hình FTP Driver

Sự tích hợp với Flysystem làm cho việc giao tiếp FTP trở nên tốt hơn; tuy nhiên, sẽ không có ví dụ cấu hình với framework mặc định ở file filesystems.php. Nếu bạn muốn cấu hình tới FTP filesystem, bạn có thể sử dụng ví dụ cấu hình dưới đây:

'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,
],

Cấu hình Rackspace Driver

Sự tích hợp với Rackspace làm cho việc giao tiếp FTP trở nên tốt hơn; tuy nhiên, các thông số cấu hình mẫu cho Rackspace không có sẵn trong file filesystems.php. Nếu muốn sử dụng, bạn có thể dùng mẫu cấu hình dưới đây:

'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',
],

Obtaining Disk Instances

Hàm Storage facade có thể được sử dụng để tương tác với bất kỳ disks được cấu hình. Ví dụ, bạn có thể sử dụng hàm put trong facade để lưu avatar vào disk. Nếu bạn gọi phương thức trong Storage facade không gọi hàm disk trước, hàm này sẽ tự động truyền vào disk:

use Illuminate\Support\Facades\Storage;

Storage::put('avatars/1', $fileContents);

Nếu ứng dụng của bạn tương tác với nhiều disks, bạn có thể sử dụng hàm disk trong Storage facade để làm việc với file trong disk:

Storage::disk('s3')->put('avatars/1', $fileContents);

Lấy Files

Hàm get có thể sử dụng để lấy thông tin một file. Nội dung dạng raw string của file sẽ được trả về. Nhớ rằng, tất cả các đường dẫn để tương đối với thư mục "root" cấu hình disk:

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

Hàm exists được dùng để kiểm tra xem một file có tồn tại trên disk hay không:

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

File URLs

Khi sử dụng local hoặc s3 drivers, bạn có thể dùng hàm url để lấy URL cho file. Nếu bạn sử dụng local driver, nó sẽ tự động thêm vào /storage cho path và trả về một relative URL của file. Nếu bạn sử dụng s3 driver, URL đầy đủ sẽ được trả về:

use Illuminate\Support\Facades\Storage;

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

Nhớ rằng, khi sử dụng local driver, tất cả files nên được public trong thư mục storage/app/public. Hơn nữa, bạn nên tạo một symbolic link vào thư mục storage/app/public.

File Metadata

Khi đọc hoặc viết files, Laravel ngoài ra còn cung cấp thông tin về files. Ví dụ, hàm size có thể dùng để lấy kích thước của file theo bytes:

use Illuminate\Support\Facades\Storage;

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

Hàm lastModified trả về thời gian dạng UNIX timestamp lần cuối cùng file được chỉnh sửa:

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

Lưu Files

Hàm put có thể được dùng để lưu nội dung file dưới dạng raw vào disk. Ngoài ra bạn có thể truyền vào một resource PHP vào hàm put, nó sẽ sử dụng stream của Flysystem. Khuyến khích sử dụng stream khi phải làm việc với file lớn:

use Illuminate\Support\Facades\Storage;

Storage::put('file.jpg', $contents);

Storage::put('file.jpg', $resource);

Automatic Streaming

Nếu bạn muốn Laravel tự động quản lý streaming một file vào folder bạn muốn lưu, bạn có thể sử dụng hàm putFile hoặc putFileAs. Hàm này nhận một instance Illuminate\Http\File hoặc Illuminate\Http\UploadedFile và sẽ tự động stream file vào nơi bạn muốn lưu:

use Illuminate\Http\File;

// Automatically calculate MD5 hash for file name...
Storage::putFile('photos', new File('/path/to/photo'));

// Manually specify a file name...
Storage::putFileAs('photos', new File('/path/to/photo'), 'photo.jpg');

Có vài điều quan trong mà bạn cần để ý khi dùng hàm putFile . Chúng chỉ nhận tên đường dẫn được chỉ định, không phải tên file. Mặc định, hàm putFile sẽ tự động sinh ra một filename based trong nội dung của file. Điều này được thực hiện bằng cách lấy một MD5 hash của nội dung file. Đường dẫn sẽ được trả về bởi hàm putFile và bạn có thể lưu đường dẫn đó, bao gồm tên file vào cơ sở dữ liệu.

Hàm putFileputFileAs ngoài ra còn chấp nhận một tham số đặc biệt "visibility" của các file. Nó sẽ rất hữu ích nếu bạn lưu file trong cloud disk như S3 và bạn muốn public quyền truy cập:

Storage::putFile('photos', new File('/path/to/photo'), 'public');

Prepending & Appending To Files

Hàm prependappend ho phép bạn dễ dàng chèn thêm nội dung vào đầu hay cuối file:

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

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

Copying & Moving Files

Hàm copy có thể dùng để copy một file tồn tại vào một folder mới trong disk, trong khi hàm move có thể được dùng để đổi tên hoặc thay đổi một file đã tồn tại vào một folder mới:

Storage::copy('old/file1.jpg', 'new/file1.jpg');

Storage::move('old/file1.jpg', 'new/file1.jpg');

File Uploads

Trong các ứng dụng web, một trong những cách phổ biến nhất là use-cases cho lưu file là lưu các file người dùng tải lên như ảnh, avatar, tài liệu. Laravel cung cấp cách rất dễ dàng để lưu là dùng hàm store để tải một file instance. Đơn giản chỉ cần gọi hàm store với đường dẫn thư mục bạn muốn lưu:

<?php

namespace App\Http\Controllers;

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

class UserAvatarController extends Controller
{
    /**
     * Update the avatar for the user.
     *
     * @param    Request  $request
     * @return  Response
     */
    public function update(Request $request)
    {
        $path = $request->file('avatar')->store('avatars');

        return $path;
    }
}

Có vài điều bạn cần chú ý trong ví dụ trên. hàm này chỉ nhận tên thư mục, không phải tên file. Mặc định, hàm storesẽ tự động sinh ra một filename based trong nội dung của file. Điều này được thực hiện bằng cách lấy một MD5 hash của nội dung file. Đường dẫn sẽ được trả về bởi hàm store và bạn có thể lưu đường dẫn đó, bao gồm tên file vào cơ sở dữ liệu.

Bạn cũng có thể dùng hàm putFile trong Storage facade thực hiện cũng tương tự:

$path = Storage::putFile('avatars', $request->file('avatar'));

Nếu bạn nhận một file có kích thước lớn, bạn có thể tự chỉ đnhij tên file như hiển thị bên dưới. Tính toán một MD5 hash cho một file cực lớn có thể tăng memory.

Specifying A File Name

Nếu bạn không muốn tên file được tự động gán khi lưu file, bạn có thể dùng hàm storeAs, nó nhận một đường dẫn, tên file, và tùy chọn disk là các tham số:

$path = $request->file('avatar')->storeAs(
    'avatars', $request->user()->id
);

Tất nhiên, bạn có thể dùng hàm putFileAs trong Storage facade, nó giống như như ví dụ trên:

$path = Storage::putFileAs(
    'avatars', $request->file('avatar'), $request->user()->id
);

Specifying A Disk

Mặc định, hàm này sẽ sử dụng disk của bạn. Nếu bạn muốn disk khác, truyền tên disk như là tham số thứ hai của hàm store:

$path = $request->file('avatar')->store(
    'avatars/'.$request->user()->id, 's3'
);

File Visibility

Trong Laravel's Flysystem, "visibility" là một cái trừu tượng của quyền file qua nhiều platforms. Files có thể được quyền public hoặc private. Khi một file được quyền public, bạn có thể chỉ rằng file này được quyền truy cập từ chỗ khác. Ví dụ, khi sử dụng S3 driver, bạn có thể nhận URLs cho public files.

Bạn có thể đặt visibility khi đặt file qua hàm put:

use Illuminate\Support\Facades\Storage;

Storage::put('file.jpg', $contents, 'public');

Nếu file đã tồn tại, có thể lấy và set thông qua hai hàm getVisibilitysetVisibility methods:

$visibility = Storage::getVisibility('file.jpg');

Storage::setVisibility('file.jpg', 'public')

Xóa Files

Hàm delete nhận một tên file hoặc một mảng tên file xóa từ disk:

use Illuminate\Support\Facades\Storage;

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

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

Các thư mục

Lấy các files trong một thư mục

Hàm files mtrả về một mảng các files trong một thư mục. Nếu bạn muốn lấy danh sách tất cả các file trong một thư mục bao gồm các thư mục con, bạn có thể sử dụng hàm allFiles:

use Illuminate\Support\Facades\Storage;

$files = Storage::files($directory);

$files = Storage::allFiles($directory);

Lấy tất cả các thư mục trong một thư mục

Hàm directories trả về một mảng tất cả các thư mục bên trong một thư mục cho trước. Thêm vào đó, bạn có thể sử dụng hàm allDirectories để lấy danh sách tất cả các thư mục trong một thư mục và các thư mục con của nó:

$directories = Storage::directories($directory);

// Recursive...
$directories = Storage::allDirectories($directory);

Tạo một thư mục

Hàm makeDirectory sẽ trả về một thư mục, bao gồm các thư mục con:

Storage::makeDirectory($directory);

Xóa một thư mục

Cuối cùng, hàm deleteDirectory được dùng để xoá một thư mục, bao gồm tất cả các file của nó:

Storage::deleteDirectory($directory);

Tùy biến Filesystems

Flysystem của Laravel cung cấp sẵn vài "drivers"; tuy nhiên, Flysystem không hề bị giới hạn bởi những drivers này mà có adapters để hỗ trợ cho các hệ thống storage khác. Bạn có thể tạo một driver riêng nếu bạn muốn sử dụng một trong những adapter bổ sung này trong ứng dụng Laravel của bạn..

Để thiết lập tùy biến filesystem bạn cần tạo một service provider như DropboxServiceProvider. Trong hàm boot của provider, bạn có thể dùng hàm Storage facade's extend để định nghĩa tùy biến driver:

<?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()
    {
        //
    }
}

Tham số đầu tiên của hàm extend là tên của driver còn tham số thứ hai là một Closure nhận vào hai biến là $app$config. Closure phải trả về một instance của League\Flysystem\Filesystem. Biến $config chứa các giá trị khai báo trong config/filesystems.php cho disk được chỉ định.

Khi mà bạn đã tạo service provider để đăng kí extension, bạn có thể sử dụng driver dropbox trong file cấu hình config/filesystem.php configuration file.

Nguồn: https://laravel.com/docs/5.3/filesystem