Appearance
WEB端直传文件到微信云托管/腾讯云存储
背景
后端服务部署在微信小程序云托管中,前端自建vue项目单独部署在微信云托管的静态资源存储中。通过后端服务提供的上传图片的接口,然后上传到云托管的对象存储,如果图片超过1M请求报错:413 Request Entity Too Large,且无法修改限制的1M大小,所以需要前端实现文件的上传处理。 
准备
1、官方文档:
微信小程序: 开发指引 /对象存储 /服务端和其他客户端 /COS-SDK服务端使用
腾讯云:文档中心>对象存储>SDK 文档>JavaScript SDK>快速入门
2、权限的调整:微信云托管默认依托于公众号、小程序,纯web网页是无法获取微信的用户信息的,所以需要自建用户体系进行用户的权限处理;另外需要修改对象存储中权限的调整,如图: 
3、安全域名的配置:文件直传云托管需要调用微信的服务,不配置的话会涉及到跨域问题,
4、云调用配置 
注意api.weixin.qq.com 相关接口前端不能直接调用,需要服务端的配合
思路
1、引入相关sdk: cos-js-sdk-v5;
2、获取临时秘钥:通过服务端去调用云调用中配置的 /_/cos/getauth,获取临时密钥相关参数;
3、设置对应的存储桶、存储区域(在云托管对象存储中可查看);
4、文件的选择上传(同时需要定义存储在桶里的对象键,通常用于表示文件的上传路径以及文件名称,如果重复会导致文件上传后覆盖);
5、上传成功后是拿不到图片的完整路径的,需要自定义拼接(根据对象存储中的外网地址+对象键),或者根据后端服务器获取;
示例
新建html直接复制下方代码并调整配置即可:
html
<!-- 选择要上传的文件 -->
<input id="fileSelector" type="file" />
<!-- 点击按钮上传 -->
<input id="submitBtn" type="submit" />
<script src="https://cdn.jsdelivr.net/npm/cos-js-sdk-v5/dist/cos-js-sdk-v5.min.js"></script>
<script>
var cos = null;
function request(url, method = "GET", data = null) {
return new Promise(function (resolve, reject) {
const xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
resolve(this.responseText);
}
});
xhr.open(method, url);
// 添加header
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader(
"Authorization", "xxxxx"
);
xhr.send(data);
});
}
cos = new COS({
getAuthorization: function (options, callback) {
// 异步获取临时密钥
request( "自定义实现获取临时密钥的后端服务,调用"
).then((res) => {
let data = JSON.parse(res).result.body;
console.log(data)
let startTime = Math.floor(Date.now() / 1000);
callback({
TmpSecretId: data.TmpSecretId,
TmpSecretKey: data.TmpSecretKey,
SecurityToken: data.Token,
// 建议返回服务器时间作为签名的开始时间,避免客户端本地时间偏差过大导致签名错误
StartTime: startTime, // 时间戳,单位秒,如:1580000000
ExpiredTime: data.ExpiredTime, // 时间戳,单位秒,如:1580000000
ScopeLimit: true, // 细粒度控制权限需要设为 true,会限制密钥只在相同请求时重复使用
});
});
},
});
function handleFileInUploading(file) {
cos.uploadFile(
{
Bucket: "xxx" /* 填写自己的 bucket,必须字段 */,
Region: "xxx" /* 存储桶所在地域,必须字段 */,
Key: "/test/xxx.jpg" /* 存储在桶里的对象键(例如:1.jpg,a/b/test.txt,图片.jpg)支持中文,必须字段 */,
Body: file, // 上传文件对象
SliceSize: 1024 * 1024 * 5 /* 触发分块上传的阈值,超过5MB使用分块上传,小于5MB使用简单上传。可自行设置,非必须 */,
onProgress: function (progressData) {
console.log(JSON.stringify(progressData));
},
},
function (err, data) {
if (err) {
console.log("上传失败", err);
} else {
console.log("上传成功");
}
}
);
return;
}
/* 选择文件 */
document.getElementById("submitBtn").onclick = function (e) {
const file = document.getElementById("fileSelector").files[0];
if (!file) {
document.getElementById("msg").innerText = "未选择上传文件";
return;
}
handleFileInUploading(file);
};
</script>如果是vue、react等环境下可以参考腾讯云-对象存储文档下的描述自定义调整引入使用:
