文件系统 / 云存储
介绍
Laravel 提供了一个强大的文件系统抽象层,这要归功于 Frank de Jonge 的优秀 PHP 包 Flysystem。Laravel 的 Flysystem 集成提供了简单易用的驱动程序,用于处理本地文件系统、Amazon S3 和 Rackspace 云存储。更好的是,切换这些存储选项非常简单,因为每个系统的 API 都保持不变。
配置
文件系统配置文件位于 config/filesystems.php
。在此文件中,您可以配置所有的“磁盘”。每个磁盘代表一个特定的存储驱动程序和存储位置。配置文件中包含了每个支持的驱动程序的示例配置。因此,只需修改配置以反映您的存储偏好和凭据。
当然,您可以配置任意数量的磁盘,甚至可以有多个使用相同驱动程序的磁盘。
公共磁盘
public
磁盘用于将要公开访问的文件。默认情况下,public
磁盘使用 local
驱动程序,并将这些文件存储在 storage/app/public
中。为了使它们可以从网络访问,您应该创建一个从 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 的 Flysystem 集成与 FTP 配合得很好;然而,框架的默认 filesystems.php
配置文件中不包含示例配置。如果您需要配置 FTP 文件系统,可以使用以下示例配置:
'ftp' => [
'driver' => 'ftp',
'host' => 'ftp.example.com',
'username' => 'your-username',
'password' => 'your-password',
// 可选的 FTP 设置...
// 'port' => 21,
// 'root' => '',
// 'passive' => true,
// 'ssl' => true,
// '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',
],
基本用法
获取磁盘实例
Storage
facade 可用于与任何已配置的磁盘交互。例如,您可以在 facade 上使用 put
方法将头像存储在默认磁盘上。如果在未先调用 disk
方法的情况下调用 Storage
facade 上的方法,则方法调用将自动传递给默认磁盘:
<?php
namespace App\Http\Controllers;
use Storage;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* 更新给定用户的头像。
*
* @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
方法访问特定磁盘。当然,您可以继续链式调用方法以在磁盘上执行方法:
$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');
文件 URL
使用 local
或 s3
驱动程序时,您可以使用 url
方法获取给定文件的 URL。如果您使用的是 local
驱动程序,这通常只会在给定路径前加上 /storage
并返回文件的相对 URL。如果您使用的是 s3
驱动程序,将返回完全限定的远程 URL。
$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
方法,这将使用 Flysystem 的底层流支持。处理大文件时,强烈推荐使用流:
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
方法:
$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
。在提供者的 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
驱动程序。