关于微信小程序上传图片到腾讯云cos上问题梳理

背景:

最近在写小程序,里面涉及了文件上传的问题,由于公司用的腾讯对象存储,之前也没有相关的上传文件技术积累,所以只能自己研究一下,web文件上传到cos的经验可以作为参照,但是却不能直接使用.

开始写:

最开始还是用了腾讯提供的sdk—cos-js-sdk-v5,但是这个在上传的时候使用putObject使用的是blob没办法使用,这个方法行不通,于是就到腾讯文档处搜索了另外一种解决方案.

腾讯文档处的解决方案—使用cos-auth 认证签名方式上传到桶内.

这种方式有点麻烦,具体可以参考文档:https://cloud.tencent.com/document/product/436/34929..

虽然一步一步按照文档里的说明去写,但是最后还是无法正常上传,总是提示SignatureDoesNotMatch,这里有一个签名的生成过程,由于不知道cos-auth里是怎么计算生成签名的,这种方式自己又放弃了..放弃的代码如下:

 

import {request} from './request';
import Taro from '@tarojs/taro';
import CosAuth from './cos-auth';

const getAuthorization = (options, callback) => {
request({
url: ‘/getSecret’,
header: {
‘content-type’: ‘application/json’
},

method: ‘get’
}).then(res => {
const credentials = res.data.credentials || {};
console.log(credentials);
callback({
XCosSecurityToken: credentials.sessionToken,
Authorization: CosAuth({
SecretId: credentials.tmpSecretId,
SecretKey: credentials.tmpSecretKey,
Method: options.Method,
Pathname: options.Pathname,
})
});

})
};

const camSafeUrlEncode = function (str) {
return encodeURIComponent(str)
.replace(/!/g, ‘%21’)
.replace(/’/g, ‘%27’)
.replace(/\(/g, ‘%28’)
.replace(/\)/g, ‘%29’)
.replace(/\*/g, ‘%2A’);
};

const uploadFile = function (filePath) {
const Key = filePath.substr(filePath.lastIndexOf(‘/’) + 1); // 这里指定上传的文件名
const signPathname = ‘/inventory/’; // PostObject 接口 Key 是放在 Body 传输,所以请求路径和签名路径是 /
const Bucket = ‘Bucket’, Region = ‘Region’;
const prefix = ‘https://’ + Bucket + ‘.cos.’ + Region + ‘.myqcloud.com/’;
console.log(prefix);
getAuthorization({Method: ‘POST’, Pathname: signPathname}, function (AuthData) {
console.log(AuthData);
Taro.uploadFile({
url: prefix,
name: ‘file’,
filePath: filePath,
formData: {
‘key’: Key,
‘success_action_status’: 200,
‘Signature’: AuthData.Authorization,
‘x-cos-security-token’: AuthData.XCosSecurityToken,
‘Content-Type’: ”,
},
success: function (res) {
console.log(res);
const url = prefix + camSafeUrlEncode(Key).replace(/%2F/g, ‘/’);
console.log(res.statusCode);
console.log(url);
},
fail: function (res) {
Taro.showToast({title: ‘上传失败’});
}
});
});
};

// const cos = () => {
// return new COS({
// getAuthorization: getAuthorization()
// });
// };

export {uploadFile};

 

上面的方式也放弃了. 看了里面的源码里面有涉及到dom的相关操作,这在小程序里是不适用的.

在网上又找了第三种方式,成功上传到cos上了

使用第三方封装好的包 —- cos-wx-sdk-v5

 

第一步: 认证..

import COS from 'cos-wx-sdk-v5';
import {request} from './request';

const getAuthorization = () => {
  return (options, callback) => {
    request({
      url:'getSecret',
      header:{
        'content-type': 'application/json'
      },
      method:'get'
    }).then(res => {
      console.log(res);
      const credentials = res.data.credentials || {};
      callback({
        TmpSecretId: credentials.tmpSecretId,
        TmpSecretKey: credentials.tmpSecretKey,
        XCosSecurityToken: credentials.sessionToken,
        ExpiredTime: res.data.expiredTime
      });
    })
  }
};

const cos = () => {
  return new COS({
    getAuthorization: getAuthorization()
  });
};

export { cos };

第二步:上传

cos().postObject({
  Bucket: Bucket,
  Region: Region,
  Key: `/inventory/${filename}`,
  FilePath: filePath

}, function (err, data) {
  console.log(data);
});
这里需要用到postObject 而不是putObject了,所以这里有一些变化,其它都差不多,但是在使用这个方式的时候也踩了一个坑,由于后端没有设置postObject的权限,
导致我这边一直报没有权限的错误.即 AccessDenied

这个问题需要后端配置来修改,在后端请求腾讯云cos的时候把该权限带上,

这个是之前putObject的权限,

后面只要加上name/cos:PostObject 这个权限即可正常使用了.

 

总结:

前后花了大概2小时的时间去解决这个问题,问题不大,但是由于是前后端分离开发的,我也不清楚后端在请求密钥的时候有哪些参数,只能靠自己盲猜,在这上面浪费了很多时间.最后在解决问题的时候,也是一步一步重新把上传过程理一遍,发现自己这边没问题,那就是其它处的问题,就这样一步一步的找到问题所在.

 

 

 

Author: kaykie

发表评论

邮箱地址不会被公开。