原由

在项目里有时候会碰到比如上传文件相关的,一般都是后端提供个接口,然后我们上传的时候后端再传到阿里OSS或者其他服务商的对象存储,然后把最终的url拿到存起来或者返回给前端,这种方式其实在上传图片的频率不高的业务场景中可能并无大碍,但是如果你的项目是相册类的,资源提供类的,总之就是有很频繁的上传文件的场景,可能服务器的带宽就有点扛不住了,那么有没有更好的解决方案呢?

服务端签名,客户端直传

其实像阿里、腾讯、七牛等云服务厂商都提供的有类似阿里的STS(Security Token Service)临时访问权限管理服务,这次就以阿里云为例,给大家介绍下如何使用STS Token,来实现在服务端签名出STS token,然后提供给前端,让前端直接用这个Token向阿里云直传文件

服务端签名,获取到STS token

我们这里直接以Node.js为例,其他语言的服务可以在阿里云的SDK参考(STS)文档里面找到,有Python、Java...

首先我们需要先装一个sts-sdk的npm包:@alicloud/sts-sdk(Nodejs version >= 8.5.0)

npm install @alicloud/sts-sdk

然后我们在utils新建一个文件oss-sts-server.js,用来生成STS Token提供给前端使用(这里只作为实例,后续大家可以自行封装)

const StsClient = require('@alicloud/sts-sdk');/*** 生成STStoken* @param accessKeyId AccessKey ID* @param accessKeySecret 从STS服务获取的临时访问密钥AccessKey Secret* @param roleArn 指定角色的ARN* @param roleSessionName 时临时Token的会话名称,自己指定用于标识你的用户,或者用于区分Token颁发给谁* @param durationSeconds token 有效事件,单位:秒* @param policy 指定的授权策略 默认为null* @return*   RequestId, 请求id*   AssumedRoleUser: {*     Arn, ${roleArn}/${roleSessionName}*     AssumedRoleId*   },*   Credentials: {*     SecurityToken, sts token*     AccessKeyId, accessKeyId*     AccessKeySecret, accessKeySecret*     Expiration 过期时间*   }*/
export default function generateSTSToken(accessKeyId, accessKeySecret, roleArn, roleSessionName = 'external-username', durationSeconds = 3600, policy = null) {const sts = new StsClient({endpoint: 'sts.aliyuncs.com', // check this from sts consoleaccessKeyId, // check this from aliyun consoleaccessKeySecret // check this from aliyun console});return res = await sts.assumeRole(roleArn, roleSessionName, policy, durationSeconds);

这个generateSTSToken函数的几个入参我来解释一下,通常我们在用阿里云或者腾讯云的时候通常会开一个RAM账户也是就子账户,我们用子账户登录到阿里云后台后,到对象存储(OSS)控制台页面,找到安全令牌(子账号授权),也就是下图中标记的地方,点击上面的前往RAM控制台按钮

随后点击开始授权按钮,之后你就可以得到accessKeyIdaccessKeySecretroleArnroleSessionName还有默认的过期时间DurationsSeconds,如下图所示,由于我之前授权过一次,所以会有左下角这个提示,这几个参数一定到保存好,不要泄露,一旦泄露,请更改RAM账户密码,并重新生成,使之前的失效

完善服务端提供的数据

这个时候其实已经拿到accessKeyIdaccessKeySecretstsTokenexpiration这四个参数了

但是客户端还需要bucket对象存储的命名空间regionbucket所在地域这两个参数

这个bucket其实就是对应的使用的那个bucket,这个可以在阿里云对象存储页面看到,有一个bucket列表,就是你要是用的那个bucket的名字

region就是某一个bucket所在的地域,比如我这个就是oss-cn-beijing

此时服务端的工作已经完结了,可以提供前端一个接口,通过鉴权之后,返回给前端这么几个参数,接下来,让我们把舞台交给我们的前端~

{accessKeyId,accessKeySecret,stsToken,bucket,region,expiration
}

前端的工作

好了,我们的后端同学的工作已经完成了~

前端er们来跟我 左边一起画个龙 在你右边 画一道彩虹(bushi)

首先我们也新建一个oss-sts-client.js/ts,然后安装一个ali-sdk/ali-oss: Aliyun OSS(open storage service) JavaScript SDK for the browser and Node.js (github.com)的包,对了不支持IE10和之前的IE版本啊

npm install ali-oss --save

然后复制下面的内容到这个文件中,用js的同学可以把ts相关的代码删掉(赶紧换到TS吧,再不换没人跟你玩了)

// 这个是服务端提供给前端的一个请求接口,返回上面我们提到的几个参数
import { getOssSTSToken } from "./request";
// @ts-ignore 忽略ts报错,ali-oss赶紧提供@types包吧,文档难看懂,库也没个文档,你们文档要是维护的好,我还用写这个?我都不想吐槽……(bushi)
import OSS from 'ali-oss'type OssStsType = {accessKeyId: stringaccessKeySecret: stringstsToken: stringexpiration: number // 这个是前端计算出的还有多少秒token过期region: stringbucket: string
}/*** 获取OSSClient* @param accessKeyId AccessKey ID* @param accessKeySecret 从STS服务获取的临时访问密钥AccessKey Secret* @param stsToken 从STS服务获取的安全令牌(SecurityToken)* @param region Bucket所在地域* @param bucket Bucket名称*/
export default async function getOssClient () {const { code, data: params } = await getOssSTSToken();if (code !== 200) return false; // 如果请求出错,在上游处理const client = new OSS({...params,refreshSTSTokenInterval: params.expiration,// 刷新临时访问凭证的时间间隔,单位为毫秒。//(这个refreshSTSToken是文档里的,为了保险各位可以在每次上传前先检查一次过期没有,不要依赖提供的这个方法)refreshSTSToken: async () => {const { code, data } = await getOssSTSToken(); // 过期后刷新tokenif (code === 200) {return data}},})return client
}

好了,到现在为止我们已经封装好了这个前端需要在上传文件的时候调用的方法了

前端维护STS Token

首先我们在前端页面第一次上传文件的时候,要调用这个getOssClient方法获取到oss-client这个对象实例,才能用这个实例进行上传操作,之后上传的时候需要先判断一下token过期了没有,如果没有过期,还是用这个实例进行上传操作,如果过期了,重新生成一个实例!

这里我们就拿一个简单的上传小文件为例(大文件分片上传,和上传成功回调(需要后端同学提供回调地址) 可以自己去看文档,我就不展开细说了)

async function uploadFileAction(file, client) {let newClient = client;// 伪代码:// if (!newClient || token is expired) { // 如果是没有实例对象或者token过期了就要重新生成//  newClient = await getOssClient(); // 调用上面我们封装好的一个方法// }const filePath = 'xxx/xxx/' // 最中在bucket中的存放的路径根据业务需要自行设置,文件名也是可以自行设置const { res, name, url } = await newClient.put(`${filePath}${file.name}`, file);if (res.status === 200) {// 这里拿到上传成功的文件的urlreturn url}
}

关于这里oss-client的维护策略,各位就仁者见仁智者见智吧,方案很多,怎么贴合业务怎么来,但是不推荐往localStoragesessionStorageindexDB里面存STS token等那些参数,你怎么就确定你的用户不是一名前端er呢?

CORS的问题

还没完啊,xdm 稍等一下,以上的都完了之后,我们在本地联调的时候如果没有开代理还是会有CORS的问题,这时候还是要去服务端去配置,找到跨域设置,进去创建一个规则,方法看你用什么就勾上什么,来源允许Headers 直接给干成*就完事了


总结

笔者也是在接触阿里云的前端直传文档之后和后端同学看文档看到头皮发麻 麻了彻底麻了 麻中麻之后,总结一篇前后端流程都可以打通的OSS前端直传的文章,如果有问题,欢迎在评论里讨论,如果能帮助到你,给咱个三连吧

一文让你彻底会用对象存储OSS的前端直传,不懂就再看一遍(bushi)相关推荐

  1. 谷粒学苑项目实战(九):实现阿里云对象存储OSS功能

    目录 一.开通阿里云对象存储OSS 二.创建bucket 三.创建操作阿里云OSS许可证 四.用代码实现头像上传功能 五.引入相关依赖 六.创建properties配置文件 七.创建主启动类 八.启动 ...

  2. oss客户端工具_干货 | 基于Go SDK操作京东云对象存储OSS的入门指南

    前言 本文介绍如何使用Go语言对京东云对象存储OSS进行基本的操作,帮助客户快速通过Go SDK接入京东云对象存储,提高应用开发的效率. 在实际操作之前,我们先看一下京东云OSS的API接口支持范围和 ...

  3. 阿里云对象存储OSS与文件存储NAS的区别

    一.简介 应用场景:选择一款存储产品,面向文档数据的存取,不会涉及到数据处理. 产品选型主要从OSS和NAS中选择一款,满足文档存储的需求. 二.NAS优缺点 NAS 是一种采用直接与网络介质相连的特 ...

  4. 使用阿里云对象存储OSS收藏老婆新垣结衣日常照

    目录 阿里云OSS官方文档 开通阿里云OSS服务 入门使用 java代码上传文件至OSS 1.准备工作:创建阿里云OSS许可证(获取对Api的访问权限) 选择继续使用 AccessKey 创建Acce ...

  5. 阿里云-对象存储 OSS > 开发指南 > 基本概念

    基本概念 更新时间:2020-09-24 10:50:53 编辑我的收藏 https://help.aliyun.com/document_detail/31827.html#title-cn1-rb ...

  6. 对象存储OSS之阿里云OSS介绍及开通

    数据.文件存储方式 一般,数据.文件的存储主要有以下几种方式: MySQL 数据(MySQL)+文件(本地IO流) 数据(MySQL)+缓存(Redis)+文件(服务器集群.fastDFS(集群).h ...

  7. 对象存储OSS基本概念讲解

    本文介绍OSS使用中的几种基本概念.给大家分享OSS的Bucket.Object.Region.Endpoint和AccessKey. Bucket 首先给大家介绍一下Bucket,Bucket是用户 ...

  8. 阿里云对象存储oss多少钱?

    阿里云对象存储oss价格是多少,根据资源包大小不同价格不同,最小的40G资源包4元左右,资源包是OSS针对不同计费项推出的优惠套餐,当您购买指定资源包后,OSS会按您实际使用情况来扣除资源包的额度.与 ...

  9. php京东云oss,干货 | 基于Go SDK操作京东云对象存储OSS的入门指南

    前言 本文介绍如何使用Go语言对京东云对象存储OSS进行基本的操作,帮助客户快速通过Go SDK接入京东云对象存储,提高应用开发的效率. 在实际操作之前,我们先看一下京东云OSS的API接口支持范围和 ...

最新文章

  1. 优达学城《DeepLearning》2-1:卷积神经网络
  2. linux firefox dns缓存,为什么有了DNS Client ,IE,Firefox,Chrome还要再缓存DNS呢?
  3. WebView点击加载的页面中的按钮时不弹出新窗口以及在加载后执行javascript
  4. ant接口自动化 junit_ant 学习(3)--结合junit形成自动化测试小框架
  5. Mysql 索引底层原理
  6. linux 系统安装 升级glibc库2.14
  7. 为什么游戏开发者不玩游戏_什么是游戏开发?
  8. hdoj1789:Doing Homework again (贪心)
  9. Win10 通过 VirtualBox安装CentOS7操作手册
  10. MYSQL的高级知识及AB复制
  11. 5款优秀的在线表单设计器
  12. 【SDE】随机微分方程(1)
  13. 入职填写的工作经历时间虚假,公司以此来辞退我怎么办?
  14. umount报错设备繁忙(device is busy)怎么处理?
  15. Android实现获取未接来电和未读短信数量的方法
  16. 2022最新MN梦奈宝塔主机系统V1.5版本+UI不错
  17. python用角度计算余弦值_Python 使用sklearn计算余弦相似度
  18. 【Paper Reading FedBCD: A Communication-Efficient Collaborative Learning Framework for DF
  19. C++14尝鲜:decltype 和 decltype(auto)
  20. MODEL COMPRESSION VIA DISTILLATION AND QUANTIZATION

热门文章

  1. 注意力机制的直观理解
  2. 51单片机实现BMP280气压计海拔高度解析(附代码)
  3. [计算机数值分析]埃特金算法加速迭代法求根过程
  4. CAD基础+常用快捷(三)
  5. Python入门到精通(4):关系与逻辑表达式
  6. JDK1.8.0_181安装以及环境配置教程(Win10系统)
  7. 解决 sublimeLinter-php 的配置问题
  8. 世界空战史上的头号王牌空中杀手
  9. Redis-AKF/CAP原则
  10. clonezilla(再生龙)克隆linux系统 操作指南