uni-app腾讯云COS直传

官网地址

对象存储 uni-app 直传实践-最佳实践-文档中心-腾讯云

https://github.com/tencentyun/cos-demo/blob/main/server/post-policy/nodejs/app.js

官方给出的直传解决方案:前端 + 服务端nodejs

这里将服务端nodejs改为js格式,自己处理数据实现直传

1. 获取COS上传文件需要用到的数据

前端要使用COS上传文件,需要提前从后端获取到

TmpSecretId:临时密钥的 tmpSecretId

TmpSecretKey:临时密钥的 tmpSecretKey

SecurityToken:临时密钥的 sessionToken,对应 header 的 x-cos-security-token 字段

ExpiredTime:<可选>临时密钥的 expiredTime,超时时刻的时间戳(也可以前端自己定义)

Bucket:自己的bucket桶名称

Region:存储桶所在地域

根据自己项目的接口调用方法,调用后端接口,获取到上述数据

2. 直传数据解析(根据官网nodejs修改而来)

安装crypto-js依赖:

npm install crypto-js
// 临时密钥服务例子
var crypto = require("crypto-js");
/**
 * 
 * @param {*} file              文件
 * @param {string} fileName     文件名,例如:'1.jpg'或'test.txt'
 * @param {object} config       COS直传解析参数{TmpSecretId, TmpSecretId, SecurityToken, Bucket, region}
 * @returns 
 */
export const handelPostPolice = (file, fileName, config) => {
    const nowTime = new Date();
    // 开始计算凭证
    var cosHost = `${config.bucket_name}.cos.${config.region}.myqcloud.com`;
    var cosKey = `${nowTime.getFullYear()}-${nowTime.getMonth() + 1}/${new Date().getTime()}${fileName.split('/').pop()}`;  /* 上传后的文件在桶中的位置,如果想要放在text文件下,可以定义为text/文件名。文件地址可以前端自己定义,也可以后端返回。 */
    var now = Math.round(Date.now() / 1000);
    var exp = now + 900;
    var qKeyTime = now + ';' + exp;
    // 生成上传要用的 policy
    var policy = JSON.stringify({
        'expiration': new Date(exp * 1000).toISOString(),
        'conditions': [
            {'q-sign-algorithm': 'sha1'},
            {'q-ak': config.access_key_id},
            {'q-sign-time': qKeyTime},
            {'bucket': config.bucket_name},
            {'key': cosKey},
        ]
    });
    // 步骤一:生成 SignKey
    var signKey = crypto.HmacSHA1(qKeyTime, config.access_key_secret).toString(crypto.enc.Hex);
    // 步骤二:生成 StringToSign
    var stringToSign = crypto.SHA1(policy).toString(crypto.enc.Hex);
    // 步骤三:生成 Signature
    var qSignature = crypto.HmacSHA1(stringToSign, signKey).toString(crypto.enc.Hex);
    var data = {
        cosHost: cosHost,
        cosKey: cosKey,
        policy: Buffer.from(policy).toString('base64'),
        qAk: config.access_key_id,
        qKeyTime: qKeyTime,
        qSignature: qSignature,
    }
    return data
}

3. 封装uni-app直传方法

import { handelPostPolice } from './handelPostPolice.js'    // 引入直传数据解析方法
​
const nowTime = new Date();
/**
 * 
 * @param {*} file              文件
 * @param {string} fileName     文件名,例如:'1.jpg'或'test.txt'
 * @param {object} res          COS上传参数{TmpSecretId, TmpSecretId, SecurityToken, Bucket, region}
 * @returns 
 */
export const uploadFileOrPic = (file, fileName, res) => {
    // COS上传数据 转 直传数据
    let opt =  handelPostPolice(file, fileName, res)
​
    // 上传图片
    return new Promise((resolve, reject) => {
        console.log('COS图片上传', opt.cosKey)
        var formData = {
            key: opt.cosKey,
            policy: opt.policy, // 这个传 policy 的 base64 字符串
            success_action_status: 200,
            'q-sign-algorithm': 'sha1',
            'q-ak': opt.qAk,
            'q-key-time': opt.qKeyTime,
            'q-signature': opt.qSignature,
        };
        uni.uploadFile({
            url: 'https://' + opt.cosHost, // 腾讯云服务器地址
            filePath: file, //本地上传文件路径
            name: 'file',
            formData: formData,
            success: (res) => {
                var fileUrl = 'https://' + opt.cosHost + '/' + camSafeUrlEncode(opt.cosKey).replace(/%2F/g, '/');
                resolve(fileUrl);
            },
            error(err) {
                reject(err);
            },
        });
    });
};
​
// 对更多字符编码的 url encode 格式
const camSafeUrlEncode = function (str) {
    return encodeURIComponent(str)
        .replace(/!/g, '%21')
        .replace(/'/g, '%27')
        .replace(/\(/g, '%28')
        .replace(/\)/g, '%29')
        .replace(/\*/g, '%2A');
};

4. 文件上传

<template>
    <view>
        <uni-file-picker ref="file" v-model="imgUrl" fileMediatype="image" mode="grid" @select="select" :sizeType="sizeType"></uni-file-picker>
    </view>
</template>
<script>
    import { uploadFileOrPic } from "@/common/uploadFile.js"
    export default {
        data() {
            return {
                imgUrl: null,
                sizeType: ['compressed'], //设置图片压缩
            }
        },
        methods: {
            // 获取上传状态
            async select(e) {
                let flieArr = e.tempFiles
                for (let i = 0; i < flieArr.length; i++) {
                    // 获取图片信息
                    let file = flieArr[i].path;
                    // 调用接口获取文件上传信息
                    const res = await this.$request(cosKey, "post");
                    // 文件上传
                    let _this = this;
                    uploadFileOrPic(file, file, res).then(url => {
                        _this.imgUrl = url
                    })
                }
            }
        }
    }
</script>

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值