这几天研究 vue 上传组件,我们知道上传必须要有服务端接受,也就是我们上传的文件必须有落地方,考虑到之前博客里的图片是托管在七牛上面,所以我就试了试将上传的文件放到七牛上面,然后就遇到一堆坑。
这里我们没有用 js-sdk 那个上传,而是通过生成 token,将其通过接口请求从而上传文件。
然后就在七牛的文档里爬坑,感觉好乱。
# Token 的获取
这里也就是要获取我们的上传凭证
# 1、构造上传策略:
let putPolicy = {
scope: config.bucket_name,
deadline:new Date().getTime() + 3600,
returnBody = `{
"name": $(fname),
"size": $(fsize),
"w": $(imageInfo.width),
"h": $(imageInfo.height),
"hash": $(etag)
}`
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- 权限(scope),指定上传的目标空间或允许覆盖的指定资源。
- 凭证有效期(deadline),即一个符合 Unix 时间戳规范的数值,单位为秒,我这里设置为一个小时候失效。
注意:因为 Unix 时间戳的创建和验证在不同的服务端进行(在业务服务器创建,在云存储服务器验证),因此开发者的业务服务器需要尽可能校准时间,否则可能出现凭证刚创建就过期等各种奇怪问题。
# 2、将上传策略序列化成为 JSON:
let put_policy = JSON.stringify(putPolicy);
1
这里就是 Json 操作,转成字符串。
# 3、对 JSON 编码的上传策略进行 URL 安全的 Base64 编码,得到待签名字符串:
这里用到了 urlsafeBase64Encode 和 base64ToUrlSafe,可以参考代码。
let encoded = urlsafeBase64Encode(put_policy);
let urlsafeBase64Encode = function (jsonFlags) {
let encoded = new Buffer(jsonFlags).toString("base64");
return base64ToUrlSafe(encoded);
};
let base64ToUrlSafe = function (v) {
return v.replace(/\//g, "_").replace(/\+/g, "-");
};
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 4、使用访问密钥(AK/SK)对上一步生成的待签名字符串计算 HMAC-SHA1 签名:
这里用到了 CryptoJS 第三方库。
let encoded_signed = hmacSha1(encoded, secretKey);
let hmacSha1 = function (encoded, secretKey) {
let hash = CryptoJS.HmacSHA1(encoded, secretKey);
return hash.toString(CryptoJS.enc.Base64);
};
1
2
3
4
5
6
2
3
4
5
6
# 5、对签名进行 URL 安全的 Base64 编码:
let _encoded_signed = base64ToUrlSafe(encoded_signed);
1
# 6、将访问密钥(AK/SK)、_encoded_signed 和 encoded 用英文符号 : 连接起来:
let upload_token = accessKey + ":" + _encoded_signed + ":" + encoded;
//eg:
upload_token =
"ctW4bSXWrUuEa_ztjW6bCG9GmpuWA0m-3L7uc83r:8ns6ppdFo5t_wtJylM0y4NBdDPQ=:eyJzY29wZSI6ImNjLWFkbWluLWJ1Y2tldCIsImRlYWRsaW5lIjoxNDk2Njg5MDA5fQ==";
1
2
3
4
5
2
3
4
5
到这里我们就得到了 token,我一开始是直接使用 qiniu 库,webpack 打包直接提示缺失依赖,不知道什么情况,我就直接按文档一步一步生成了,也很简单。
有了 token 之后我们就可以发请求了,我这里先用了饿了么的上传组件,配置如下:
<el-upload
class="avatar-uploader"
action="http://up-z2.qiniu.com/"
:show-file-list="false"
:data='form'
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload">
<img v-if="imageUrl" :src="imageUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
data() {
return {
imageUrl: '',
form: {
token: '',
key: null
}
}
},
//我这里把获取token封装在接口里面了,官方不建议在前端生成。
created() {
getToken().then((res) => {
this.form.token = res.data.token;
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
到这里就可以正常的上传图片了,上传很粗糙,这里主要是说和七牛的搭配,上面的示例代码可能不能直接运行,可以参考一下,大家也可以在我的github上看,Demo 示例链接,欢迎指正。
七牛上传 api 参考:上传凭证