纯前端上传文件到又拍云-保姆级教程🚀🚀🚀
本文旨在介绍 纯前端上传文件到又拍云、又拍云签名算法、又拍云存储配置相关等 ;帮助开发者快速了解并掌握该上传方法, 点赞+收藏=学会了 🤣
前言
最近在重构 定制头像2.0 开源项目时,接触到了又拍云文件上传;遇到些许迷惑,踩了一些坑;遂以本文记录,望诸位能少踩些许坑~
若只想看代码请下滑至 完整代码 或前往 前端上传文件demo 源代码 ;欲知内部细节,来和采黎一起往下看吧~
相关地址
上传方式
又拍云上传文件的方式有以上三种,我们今天讲的是 前端直传 ,所以用 FORM API 普通上传,上传文件就以图片举例。
起步
- 在又拍云控制台打开 云产品-云存储
- 点击 创建云存储服务 (已有云存储服务可跳过该步骤),这里我创建了一个测试用的云存储------xiaoli-test(bucket名,上传需要)
- 进入功能配置-存储管理页,在最下方找到 操作员授权,新建一个操作员。
新建后我们便得到一个操作名为 test ,密码为 DrKNn10NKKWukeUPur0N1a0D8ET2vEfV (请牢记该密码),并为操作员赋予可写入权限。
- 进入文件管理后,我们创建一个 img 的文件目录,用于存放上传的图片。
FORM API 上传
请求方法
js
curl http://v0.api.upyun.com/<bucket> \
-F authorization="UPYUN <Operator>:<Signature>" \
-F file=@<filename> \
-F policy=<policy> \
# 其他参数...
下文所需字段
- bucket(云存储服务的名称) :
xiaoli-test
- username(操作员名称) :
test
- password(操作员密码) :
0LjHlUNs8n0RWbEPi3c0BB3dOJBkfhwd
- path(文件上传路径) :
/img
- testCdnUrl(测试域名) :
http://xiaoli-test.test.upcdn.net
测试域名格式:bucket.test.upcdn.net , .test.upcdn.net 为固定后缀
请求方式【post】
请求域名
官方提供了4个请求地址, 我们这里用 v0.api.upyun.com
。
- 智能选路(推荐):
v0.api.upyun.com
- 电信线路:
v1.api.upyun.com
- 联通(网通)线路:
v2.api.upyun.com
- 移动(铁通)线路:
v3.api.upyun.com
js
// 请求地址:https://v0.api.upyun.com/<bucket>
https://v0.api.upyun.com/xiaoli-test
请求参数(必传)
file
表单file文件policy
policyauthorization
授权签名
policy 算法
所需字段如下
bucket
云存储服务的名称expiration
过期时间(时间戳秒),这里我们设置10分钟过期。save-key
文件保存的路径(路径包含文件名)
类型 | 格式 | 说明 |
---|---|---|
绝对值 | String | 指定具体的路径,如: /path/to/file.txt |
时间类 | {year} {mon} {day} {hour} {min} {sec} | 日期、时间相关内容(UTC 时间) |
md5 类 | {filemd5} | 文件的 md5 值 |
随机类 | {random} {random32} | 16 位或 32 位随机字符和数字 |
文件名 | {filename} {suffix} {.suffix} | 上传文件的文件名及扩展名 |
官方那个提供了5种 save-key
,这里我们用最后一种文件名的方式({filename}{.suffix}为帮我们提取到文件名)。
js
const saveKey' = `${ this.path }/{filename}{.suffix}` /* 得到文件路径 /img/a.png */
计算方法
js
const policyObj = {
bucket: this.bucket,
'save-key': `${ this.path }/{filename}{.suffix}`,
expiration: new Date().getTime() + 600, /* 过期时间,在当前时间+10分钟 */
}
/* 将所需字段转string再转为base64 */
const policy = btoa(JSON.stringify(policyObj))
uploadData.append('policy', policy);
authorization 算法
所需字段如下
policy
上面计算的policyusername
操作员名称password
操作员密码
还需引入 cdn.xiaoli.vip/tools/upyun... 文件,里面提供了计算签名所需的 HexMD5
和 b64hamcsha1
hash算法
authorization 组成格式
js
UPYUN <Operator>:<Signature>
UPYUN 操作名:<Signature>
// Signature = Base64 (HMAC-SHA1 (<Password>,<Method>&<URI>&<Policy>))
// HMAC-SHA1 返回的原生二进制数据进行 Base64 编码
// Password 密码转md5后
// Method 请求方法 POST
// URI 请求路径 /bucket, /xiaoli-test
计算方法
js
/* 密码转md */
const passwordMd5 = HexMD5.MD5(this.password).toString(HexMD5.enc.Hex)
/* [Method-请求方法, URI-请求路径, policy] */
const arr = ['POST', `/${ this.bucket }`, policy]
const authorization = `UPYUN ${ this.username }:${ b64hamcsha1(passwordMd5, arr.join('&')) }`
uploadData.append('authorization', authorization);
返回参数
- 上传成功:返回
code = 200
、message = ok
即上传成功。
参数 | 说明 |
---|---|
code | 状态码,200 表示上传成功 |
message | URL encoding 的描述信息,ok 表示上传成功,其他的表示错误信息 |
url | URL encoding 的文件保存路径 |
time | UNIX UTC 时间戳,单位秒 |
image-width | 图片的宽。上传文件是图片时,才存在 |
image-height | 图片的高。上传文件是图片时,才存在 |
image-type | 图片类型。上传文件是图片时,才存在 |
image-frames | 图片帧数。上传文件是图片时,才存在 |
- 上传失败:返回相应的出错信息,具体请参阅「API 错误码表」。
注意事项
- 每个请求只能上传一个文件
- 请求的参数名和参数值 区分大小写,切记区分大小写。
完整代码
html
html
<input id="upload" type="file" accept=".jpg,.png" @change="uploadImg" />
js(vue)
js
data() {
return {
bucket: 'xiaoli-test',
username: 'test',
password: '0LjHlUNs8n0RWbEPi3c0BB3dOJBkfhwd',
path: '/img',
testCdnUrl: 'http://xiaoli-test.test.upcdn.net',
imgLocalUrl: '',
uploadImgList: []
};
},
uploadImg (e) {
const file = e.target.files[0]
this.imgLocalUrl = URL.createObjectURL(file)
/* 创建FormData */
const uploadData = new FormData()
uploadData.append('file', file);
const url = `https://v0.api.upyun.com/${ this.bucket }`
/* 计算policy */
const policyObj = {
bucket: this.bucket,
'save-key': `${ this.path }/{filename}{.suffix}`,
expiration: new Date().getTime() + 600, /* 过期时间,在当前时间+10分钟 */
}
const policy = btoa(JSON.stringify(policyObj))
uploadData.append('policy', policy);
/* 计算 Authorization */
const passwordMd5 = HexMD5.MD5(this.password).toString(HexMD5.enc.Hex)
/* [Method-请求方法, URI-请求路径, policy] */
const arr = ['POST', `/${ this.bucket }`, policy]
const authorization = `UPYUN ${ this.username }:${ b64hamcsha1(passwordMd5, arr.join('&')) }`
uploadData.append('authorization', authorization);
axios({ method: 'POST', url, data: uploadData }).then((res) => {
this.uploadImgList.push(this.testCdnUrl + res.data.url)
}).catch(e => {
console.error('上传失败', e)
alert('上传失败')
})
/* 清除input的值,解决二次上传文件未触发 */
document.getElementById('upload').value = ''
}
所有代码已上传至github
, 链接直通车,欢迎start~
鸣谢
使用又拍云
应该有近一年了,速度和稳定性都很nice。在很多开源小项目中都有使用,感谢又拍云免费提供云存储、cdn等服务!
余音
本文至此已近尾声,若发现有误处,请大家及时指正,小黎会第一时间更正🙏。欢迎大家一键三连~ 秋风来,蝶花开,再见便是国旗头像
了,再会!