这两天有个需求,要微信小程序跟QQ小程序通过阿里的OSS储存,存放静态资源,遇到了挺多问题,记录一下~~~
文档:此处
其实这个是被误导了,也怪自己没有仔细看文档,不该有这一步,但是做了就记录一下,正好多了解nodejs环境与浏览器环境 API的差别。
服务器直传里面的方法,失败了:浏览器环境没有Buffer 对象
一下是OSS中的DEMO:
只能找方法生成
// 创建一个类似于 Node.js Buffer 的类
class Buffer2 {
constructor(data) {
this.data = data;
}
// 将string类型转成Buffer数组
static from(source) {
if (typeof source === 'string') {
// 如果源是字符串,则将其编码为指定的编码格式
const encoder = new TextEncoder();
let encodedData = encoder.encode(source)
console.log("encodedData:", encodedData);
return new Buffer2(encodedData)
const hexString = Array.from(encodedData).map(byte => byte.toString(16).padStart(2, '0'));
return new Buffer2(hexString);
} else {
throw new Error("不知道什么数据...")
}
}
base64Encode(str) {
const base64Chars =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
let result = '';
for (let i = 0; i < str.length; i += 3) {
const char1 = str.charCodeAt(i);
const char2 = str.charCodeAt(i + 1);
const char3 = str.charCodeAt(i + 2);
const byte1 = char1 >> 2;
const byte2 = ((char1 & 3) << 4) | (char2 >> 4);
const byte3 = ((char2 & 15) << 2) | (char3 >> 6);
const byte4 = char3 & 63;
result +=
base64Chars.charAt(byte1) +
base64Chars.charAt(byte2) +
base64Chars.charAt(byte3) +
base64Chars.charAt(byte4);
}
// Handle padding
const padding = str.length % 3;
if (padding === 1) {
result = result.slice(0, -2) + '==';
} else if (padding === 2) {
result = result.slice(0, -1) + '=';
}
return result;
}
toString(encoding = 'base64') {
if (encoding === 'base64') {
const binary = [];
const bytes = new Uint8Array(this.data);
for (let i = 0; i < bytes.length; i++) {
binary.push(String.fromCharCode(bytes[i]));
}
return this.base64Encode(binary.join(''));
} else {
throw new Error('Unsupported encoding');
}
}
}
let obj = { a: 1, b: 2 }
let buf = Buffer2.from(JSON.stringify(obj))
console.log("buf:", buf);
console.log(buf.toString("base64"));
用简单的对象obj进行测试~
=====
接下来尝试生成DEMO例子中的签名,看看结果一不一样
这里为了数据比对,就将DEMO中的srcT(源代码是实时时间)写死了。
const crypto = require("crypto-js");
class MpUploadOssHelper {
constructor(options) {
this.accessKeyId = options.access_key_id;
this.accessKeySecret = options.access_key_secret;
// 限制参数的生效时间,单位为小时,默认值为1。
this.timeout = options.timeout || 1;
// 限制上传文件的大小,单位为MB,默认值为10。
this.maxSize = options.maxSize || 10;
}
createUploadParams() {
const policy = this.getPolicyBase64();
const signature = this.signature(policy);
return {
OSSAccessKeyId: this.accessKeyId,
policy: policy,
signature: signature,
};
}
getPolicyBase64() {
let date = new Date();
// 设置policy过期时间。
date.setHours(date.getHours() + this.timeout);
let srcT = date.toISOString();
console.log(srcT);
srcT = '2023-09-08T06:59:34.489Z'
const policyText = {
expiration: srcT,
conditions: [
// 限制上传文件大小。
["content-length-range", 0, this.maxSize * 1024 * 1024],
],
};
console.log("policyText:", policyText);
const buffer = Buffer.from(JSON.stringify(policyText));
console.log("sss", buffer);
return buffer.toString("base64");
}
signature(policy) {
return crypto.enc.Base64.stringify(
crypto.HmacSHA1(policy, this.accessKeySecret)
);
}
}
const mpHelper = new MpUploadOssHelper({
access_key_id: "xxxxxxxxxxxxxxxx",
access_key_secret: "xxxxxxxxxxxxxxxxxxxxxxxx"
})
// 生成参数。
const params = mpHelper.createUploadParams();
console.log(params);
结果如下:
都是使用一样的代码,只不过小程序用了自定义的class Buffer2
到这里了,就可以证明基本没问题了~
那试试发送请求有无问题???
肯定有问题啦~~~
参考官网的wx.uploadFile,一系列操作后:
该错误与下方的客户端签名直传一样~
WAServiceMainContext.js?t=wechat&s=1694156563411&v=3.0.1:1 TypeError: Cannot read property 'sigBytes' of undefined
at new init (vendor.js? [sm]:43703)
at Object.HmacSHA1 (vendor.js? [sm]:41454)
at MpUploadOssHelper.signature (ossHelper.js? [sm]:93)
at MpUploadOssHelper.createUploadParams (ossHelper.js? [sm]:61)
at _callee$ (uploadFile2.js? [sm]:45)
at s (regeneratorRuntime.js:1)
at Generator.<anonymous> (regeneratorRuntime.js:1)
at Generator.next (regeneratorRuntime.js:1)
at asyncGeneratorStep (asyncToGenerator.js:1)
at c (asyncToGenerator.js:1)(env: Windows,mp,1.06.2308291; lib: 3.0.1)
如下~
参考:此处
调用 crypto.HmacSHA1 出现 sigBytes
oss uniapp 客户端直传,显示 TypeError: Cannot read property ‘sigBytes’ of undefined
找到问题了~是自己的问题,给的提示也太那个了,console.log 一下参数。。。
crypto.HmacSHA1方法中,第二个参数为undefined...
之前实在搞不定,决定去找客服找解决方案,也记录一下,~~~
在vue项目中通过
npm i ali-oss
,已经可以实现上传,具体可以参考官网DEMO
官网:此处
想着自己通过uni.getFileSystemManager() 获取本地文件权限,再转成Blob对象,好家伙,微信开发者工具直接找不到,NND~~~
大平台,看官方文档就好了,不要相信自己~