这是我参与8月更文挑战的第31天,活动详情查看:8月更文挑战
一、文件上传服务器解决方案
1.1 文件直接上传服务器的弊端
1、如果文件上传经过我们服务器的话,它会占用服务器的带宽。 2、如果文件上传到服务器,还会占用我们服务器硬盘的空间。
1.2 解决方案
我们可以使用第三方的存储,例如阿里云的对象存储oss
。让第三方存储来托管我们的文件。
先去阿里云上面开通对象存储OSS
。开通后进入对象存储OSS
管理控制台:
进入之后,我们去购买资源包:
1.3 Bucket概念
购买完之后我们再来看下这个Bucket
的概念,你可以直接把oss
理解成远程的电脑,我们把文件存储在这上面,而Bucket
的话相当于电脑磁盘分盘。可以把文件分在不同的盘。
我们来创建一个我们这次项目的Bucket
库:
注意这个地域的话最好选在你服务器所在的区域,会减少一些费用。测试的项目一些功能就不开通,真正上线的项目最好全开。
创建完Bucket
的之后,我们直接看它使用文档,
我们这边的话肯定不使用
sdk
的方式,因为这种方式的话有弊端,我们既然使用了OSS
存储的话就是想不经过服务器,减少服务的带宽,和存储空间的压力,而使用这种sdk
的方式的话,还是从客户端发送请求到服务端,然后服务端拿到这个文件进去请求存入到OSS
存储中。这种方式还是占用了服务器的带宽和存储空间。没有意义。我们建议直接采用最佳实践的例子来完成:
由web
端直接上传数据至我们的OSS
云存储上,减少服务器的带宽和存储空间。
1.4 客户端演示
下载浏览器客户端代码:
我们直接打开下载的例子:
用编辑器打开upload.js
,可以看到accessid
和accesskey
直接暴露在浏览器这是非常危险的。
我们暂且不管其安全性,先用这个例子来演示跑起来,再进行服务端签名的优化:
点击个人信息找到
accesskey
:
accesskey
的权限非常的高,所以这边建议创建子用户accesskey
,这样哪怕是子用户的泄露,我们还可以把子用户的accesskey
删除就安全了:
创建完用户记住信息,因为这个只显示一次。
创建完用户后给用户赋予权限:
接着将upload.js
里的accessid
和accesskey
替换成刚刚创建的accessid
和accesskey
。
host
要选择我们Bucket
的域名:
接着在Bucket
修改权限设置,设置跨域问题:
修改
demo
里的过期时间:
1.5 测试效果
二、采用后端签名方式(最佳实践)
我们直接采用第三方,上Packagist上去找关于laravel
相关的:
运行安装命令:
composer require "iidestiny/laravel-filesystem-oss"
;
在config/filesystems.php
配置文件中加驱动:
'oss' => [
'driver' => 'oss',
'root' => '', // 设置上传时根前缀
'access_key' => env('OSS_ACCESS_KEY'),
'secret_key' => env('OSS_SECRET_KEY'),
'endpoint' => env('OSS_ENDPOINT'), // 使用 ssl 这里设置如: https://oss-cn-beijing.aliyuncs.com
'bucket' => env('OSS_BUCKET'),
'isCName' => env('OSS_IS_CNAME', false), // 如果 isCname 为 false,endpoint 应配置 oss 提供的域名如:`oss-cn-beijing.aliyuncs.com`,否则为自定义域名,,cname 或 cdn 请自行到阿里 oss 后台配置并绑定 bucket
// 如果有更多的 bucket 需要切换,就添加所有bucket,默认的 bucket 填写到上面,不要加到 buckets 中
'buckets'=>[
'test'=>[
'access_key' => env('OSS_ACCESS_KEY'),
'secret_key' => env('OSS_SECRET_KEY'),
'bucket' => env('OSS_TEST_BUCKET'),
'endpoint' => env('OSS_TEST_ENDPOINT'),
'isCName' => env('OSS_TEST_IS_CNAME', false),
],
//...
],
],
然后在.env
中加入:
OSS_ENDPOINT
就是地域节点的域名:
接着去生成token
。
在认证用户auth.php
中定义一个路由:
// 阿里云oss token
$api->get('oss/token', [OssController::class, 'token']);
创建一个控制器:
运行命令:php artisan make:controller Auth/OssController
:
在
OssController.php
中写入:
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\BaseController;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class OssController extends BaseController
{
/**
* 生成oss上传token
*/
public function token()
{
$disk = Storage::disk('oss');
/**
* 1. 前缀如:'images/'
* 2. 回调服务器 url
* 3. 回调自定义参数,oss 回传应用服务器时会带上
* 4. 当前直传配置链接有效期
*/
$config = $disk->signatureConfig($prefix = '/', $callBackUrl = '', $customData = [], $expire = 30);
$configArr = json_decode($config, true);
return $this->response->array($configArr);
}
}
测试:
就在前端传入获取到的这些配置:
图片配置完整域名:
在.env
中加入oss
域名前缀:
在
config/filesystems.php
中加入:
在商品GoodTransformer.php
加入:
这样写的话比较麻烦,我们可以写在helpers.php
文件中,这样在其他地方需要使用到的,就直接写函数就可以了:
/**
* 清空所有分类缓存
*/
if (!function_exists('oss_url')) {
function oss_url ($key) {
return config('filesystems.disks.oss.bucket_url').$key;
}
}
然后修改
GoodTransformer.php
:
效果:
其他地方有关于图片的处理都是这样的。例:
效果:
使用
oss
最佳实践,至于图片名称的话,由前端那边提供图片名称,然后字段返回拼接字段就可以显示了。
在学习的php的路上,如果你觉得本文对你有所帮助的话,那就请关注点赞评论三连吧,谢谢,你的肯定是我写博的另一个支持。