梦入琼楼寒有月,行过石树冻无烟

Laravel Flysystem

Laravel 通过 Frank de Jonge 内的 Flysystem 扩展包为开发者提供了一个强大的文件系统抽象概念。配置 Flysystem 的配置在config/filesystem.php中,再次我们可以配置所有的文件存储位置以及文件磁盘。

public

public 磁盘被称之为“公共磁盘”,因此他主要适用与公开的访问文件,默认情况下由本地(local)进行驱动,并存储在storage/app/publi目录下。如果需要让此在网络情况下也可以访问,需要创建public/storagestoraage/app/public的符号链接。

这种方式可以将公开文件都保存在一个目录下,以及在使用停机时间部署时可以轻松在不同的部署之间共享这些文件。

此时我们可以通过使用 下述 artisan 命令来创建符号链接:

1
2
$ php artisan storage:link
The [public/storage] directory has been linked.

权限

同样的在 public 中,可见行为目录的 755(拥有读、写、执行权限)和文件的644(拥有读写权限),我们也可修改filesystem配置文件中的权限映射:

1
2
3
4
5
6
7
8
9
10
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
'permissions' =>[
'file'=>[
'public'=>0600,
'private'=>0700
]
]
],

在上述配置中,我们将 /public 赋予了0600即只有读写权限,而在 /private 目录下则赋予了 0700的可读、写、执行权限。

文件上传

local

在 Laravel 中,要实现文件的上传需要通过使用 file以及store的搭配,通过 file来告诉 Laravel:”你需要上传谁,及获取谁的表单”。而store则是告诉 Laravel 你需要存储在哪个目录下

1
2
//web.php
Route::post('/upload',"PostController@update");
1
2
3
4
5
6
7
{{--inbar.blade.php--}}
<form action="/upload" method="post" enctype="multipart/form-data">
@csrf
<input type="hidden" name="_token" value="<?php echo csrf_token()?>">
<input type="file" name="img">
<button type="submit">Up File</button>
</form>
1
2
3
4
5
6
7
8
9
10
11
12
//    Controller
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function update(Request $request)
{
$path = $request->file('img')->store('avatars');
return $path;
}

在上述的 Controller code 中,我们通过了获取名为 img 表单所上传的文件后存储至avatarsstorage/app/avatars目录下。值得注意的是默认情况下 store方法会自动生成一个唯一ID 作为文件名称


当我们上传图像的时候,将会在 avatars目录下显示出我们刚刚上传的图像,并经过了store来自动生成一个唯一的ID作为文件名称。

Tencent cos


在上面我们介绍了 Laravel 文件的存储中,说到了文件磁盘,其中主要可以进行本地和远程的文件上传。在 Laravel 我们通常会使用国内较快的 腾讯云 COS,而 Laravel 默认的是 AWS s3,本文主要使用 Tencent cloud cosv5 作为演示,首先需要安装依赖:

安装与配置

1
composer require freyo/flysystem-qcloud-cos-v5

当一切完成之后想 config/app.php 文件内providers中添加以下信息:

1
2
3
4
5
6
7
8

'providers' => [

/*
* Laravel Framework Service Providers...
*/
……
Freyo\Flysystem\QcloudCOSv5\ServiceProvider::class,
env and filesystems

在然后将下述 code 粘贴并修改到 .end文件中:

需要参考腾讯云 COS 管理内和密钥页面进行填写

1
2
3
4
5
6
7
8
9
10
11
12
13
COSV5_APP_ID=
COSV5_SECRET_ID=
COSV5_SECRET_KEY=
COSV5_TOKEN=null
COSV5_TIMEOUT=60
COSV5_CONNECT_TIMEOUT=60
COSV5_BUCKET=
COSV5_REGION=
COSV5_CDN=
COSV5_SCHEME=https
COSV5_READ_FROM_CDN=false
COSV5_CDN_KEY=
COSV5_ENCRYPT=false

当修改完成后将下述 code 复制到 config/filesystems.php 文件内的disks下,无需修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
'disks' => [
……
'cosv5' => [
'driver' => 'cosv5',
'region' => env('COSV5_REGION', 'ap-guangzhou'),
'credentials' => [
'appId' => env('COSV5_APP_ID'),
'secretId' => env('COSV5_SECRET_ID'),
'secretKey' => env('COSV5_SECRET_KEY'),
],
'timeout' => env('COSV5_TIMEOUT', 60),
'connect_timeout' => env('COSV5_CONNECT_TIMEOUT', 60),
'bucket' => env('COSV5_BUCKET'),
'cdn' => env('COSV5_CDN'),
'scheme' => env('COSV5_SCHEME', 'https'),
'read_from_cdn' => env('COSV5_READ_FROM_CDN', false),
],

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//    Controller
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function update(Request $request)
{
/*
* 1.获取 名为 img 表单所提交的文件
* 2.选择 cosv5 作为文件磁盘
* 3.将 $file 存储至 "picture_class" 目录下
* 4.生成并返回该文件的 url。
*/

$file = $request->file('img');
$disk = Storage::disk('cosv5');
$file_content = $disk->put("picture_class",$file);
$file_url = $disk->url($file_content);
return ($file_url);
}
文件名称

在 local 一节中我们说道了 store方法会自动生成一个唯一的ID 作为文件的名称,因此在提交的时候唯一性是保证了,但是可读性会大大缩小。因此我们可以通过下述几个方法来对文件名称进行操作:

ID DA
getClientOriginalName 获取原来的文件名
getClientOriginalExtension 获取文件的扩展名
getClientMimeType 文件的类型
1
2
3
4
5
6
7
8
$file = $request->file('img');
$extension = $file->getClientOriginalName();
$filename = date('Y-m-d G_i_s') . ".".$extension;

$disk = Storage::disk('cosv5');
$file_content = $disk->putFileAs('picture_class',$file,$filename);
$file_url = $disk->url($file_content);
return $file_url;

除了上述的 getClient 方法外,我们还需要配合date方法来共同完成,因此我们通过使用 dataY-m-d G_i_s 来进行实现,分别表示 年份-月份-日期 小时_分周_秒数 等,最终输出 2021-05-12 23_46_00

⬅️ Go back