纯前端实现又拍云文件上传-保姆级教程🚀🚀🚀

纯前端上传文件到又拍云-保姆级教程🚀🚀🚀

本文旨在介绍 纯前端上传文件到又拍云、又拍云签名算法、又拍云存储配置相关等 ;帮助开发者快速了解并掌握该上传方法, 点赞+收藏=学会了 🤣

前言

最近在重构 定制头像2.0 开源项目时,接触到了又拍云文件上传;遇到些许迷惑,踩了一些坑;遂以本文记录,望诸位能少踩些许坑~

若只想看代码请下滑至 完整代码 或前往 前端上传文件demo 源代码 ;欲知内部细节,来和采黎一起往下看吧~

相关地址

上传方式

又拍云上传文件的方式有以上三种,我们今天讲的是 前端直传 ,所以用 FORM API 普通上传,上传文件就以图片举例。

起步

  1. 在又拍云控制台打开 云产品-云存储
  1. 点击 创建云存储服务 (已有云存储服务可跳过该步骤),这里我创建了一个测试用的云存储------xiaoli-test(bucket名,上传需要)
  1. 进入功能配置-存储管理页,在最下方找到 操作员授权,新建一个操作员。

新建后我们便得到一个操作名为 test ,密码为 DrKNn10NKKWukeUPur0N1a0D8ET2vEfV (请牢记该密码),并为操作员赋予可写入权限。

  1. 进入文件管理后,我们创建一个 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 policy
  • authorization 授权签名

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 上面计算的policy
  • username 操作员名称
  • password 操作员密码

还需引入 cdn.xiaoli.vip/tools/upyun... 文件,里面提供了计算签名所需的 HexMD5b64hamcsha1 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 = 200message = 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等服务!

余音

本文至此已近尾声,若发现有误处,请大家及时指正,小黎会第一时间更正🙏。欢迎大家一键三连~ 秋风来,蝶花开,再见便是国旗头像了,再会!

相关推荐
工业互联网专业12 分钟前
毕业设计选题:基于springboot+vue+uniapp的驾校报名小程序
vue.js·spring boot·小程序·uni-app·毕业设计·源码·课程设计
J不A秃V头A41 分钟前
Vue3:编写一个插件(进阶)
前端·vue.js
司篂篂1 小时前
axios二次封装
前端·javascript·vue.js
姚*鸿的博客2 小时前
pinia在vue3中的使用
前端·javascript·vue.js
天下无贼!3 小时前
2024年最新版Vue3学习笔记
前端·vue.js·笔记·学习·vue
Jiaberrr3 小时前
JS实现树形结构数据中特定节点及其子节点显示属性设置的技巧(可用于树形节点过滤筛选)
前端·javascript·tree·树形·过滤筛选
我码玄黄4 小时前
THREE.js:网页上的3D世界构建者
开发语言·javascript·3d
爱喝水的小鼠4 小时前
Vue3(一) Vite创建Vue3工程,选项式API与组合式API;setup的使用;Vue中的响应式ref,reactive
前端·javascript·vue.js
小晗同学4 小时前
Vue 实现高级穿梭框 Transfer 封装
javascript·vue.js·elementui
WeiShuai4 小时前
vue-cli3使用DllPlugin优化webpack打包性能
前端·javascript