uniapp 上传静态资源-- 微信小程序跟QQ小程序上传静态资源到阿里的对象存储 OSS

概述

这两天有个需求,要微信小程序跟QQ小程序通过阿里的OSS储存,存放静态资源,遇到了挺多问题,记录一下~~~

文档:此处

服务器签名

其实这个是被误导了,也怪自己没有仔细看文档,不该有这一步,但是做了就记录一下,正好多了解nodejs环境与浏览器环境 API的差别。

服务器直传里面的方法,失败了:浏览器环境没有Buffer 对象
一下是OSS中的DEMO:

BUG1:浏览器环境没有Buffer对象

uniapp 上传静态资源-- 微信小程序跟QQ小程序上传静态资源到阿里的对象存储 OSS_第1张图片

只能找方法生成

// 创建一个类似于 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进行测试~

浏览器环境测试自定义Buffer

uniapp 上传静态资源-- 微信小程序跟QQ小程序上传静态资源到阿里的对象存储 OSS_第2张图片

原生node环境使用原生Buffer

uniapp 上传静态资源-- 微信小程序跟QQ小程序上传静态资源到阿里的对象存储 OSS_第3张图片
结果一样了~~~

=====

接下来尝试生成DEMO例子中的签名,看看结果一不一样
这里为了数据比对,就将DEMO中的srcT(源代码是实时时间)写死了。
uniapp 上传静态资源-- 微信小程序跟QQ小程序上传静态资源到阿里的对象存储 OSS_第4张图片

原生node环境 生成签名

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);

结果如下:

uniapp 上传静态资源-- 微信小程序跟QQ小程序上传静态资源到阿里的对象存储 OSS_第5张图片

微信小程序 生成签名

都是使用一样的代码,只不过小程序用了自定义的class Buffer2

uniapp 上传静态资源-- 微信小程序跟QQ小程序上传静态资源到阿里的对象存储 OSS_第6张图片

到这里了,就可以证明基本没问题了~
那试试发送请求有无问题???

肯定有问题啦~~~
参考官网的wx.uploadFile,一系列操作后:
uniapp 上传静态资源-- 微信小程序跟QQ小程序上传静态资源到阿里的对象存储 OSS_第7张图片
该错误与下方的客户端签名直传一样~

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)

如下~


客户端签名

参考:此处

BUG1:crypto-js 库 sigBytes

调用 crypto.HmacSHA1 出现 sigBytes

oss uniapp 客户端直传,显示 TypeError: Cannot read property ‘sigBytes’ of undefined

uniapp 上传静态资源-- 微信小程序跟QQ小程序上传静态资源到阿里的对象存储 OSS_第8张图片
追溯源头,因为使用了crypto-js

uniapp 上传静态资源-- 微信小程序跟QQ小程序上传静态资源到阿里的对象存储 OSS_第9张图片

找到问题了~是自己的问题,给的提示也太那个了,console.log 一下参数。。。
uniapp 上传静态资源-- 微信小程序跟QQ小程序上传静态资源到阿里的对象存储 OSS_第10张图片
crypto.HmacSHA1方法中,第二个参数为undefined...


之前实在搞不定,决定去找客服找解决方案,也记录一下,~~~

uniapp 上传静态资源-- 微信小程序跟QQ小程序上传静态资源到阿里的对象存储 OSS_第11张图片

微信小程序调用OSS SDK

在vue项目中通过npm i ali-oss,已经可以实现上传,具体可以参考官网DEMO
官网:此处

Bug1:微信API导出的文件只是path

并不是浏览器常用的blob
uniapp 上传静态资源-- 微信小程序跟QQ小程序上传静态资源到阿里的对象存储 OSS_第12张图片

Bug2:微信小程序中没有Blob对象

想着自己通过uni.getFileSystemManager() 获取本地文件权限,再转成Blob对象,好家伙,微信开发者工具直接找不到,NND~~~

uniapp 上传静态资源-- 微信小程序跟QQ小程序上传静态资源到阿里的对象存储 OSS_第13张图片

后来继续看到了文档,这OSS售后,沃日 T。T …
uniapp 上传静态资源-- 微信小程序跟QQ小程序上传静态资源到阿里的对象存储 OSS_第14张图片

总结

大平台,看官方文档就好了,不要相信自己~

你可能感兴趣的:(uniapp,小程序,uni-app,微信小程序)