华为云对象存储OBS小程序直传OBS_云淘科技

背景信息

微信小程序作为当下流行的移动应用,具有广泛的应用场景。如何通过微信小程序上传文件至对象存储服务OBS成为了一个热点问题,本文将通过一个示例程序进行演示。

注意事项

计算签名时依赖引用“crypto-js”及“js-base64”两个开源组件,因此需要在微信小程序项目中设置使用NPM模块。
在微信小程序中进行编译时,如果在引入“crypto-js”包时出现“Maximum call stack size exceed”报错,请升级微信小程序开发客户端至最新版本。
上传过程中返回405时,请检查指定的endpoint是否为对应上传桶的桶域名。

操作步骤

设置桶的跨域访问权限。

微信小程序基于BrowerJS进行开发,受同源安全策略的要求,不同域间的网站脚本和内容如需交互,需要配置跨域资源共享(CORS)规范。华为云对象存储服务OBS支持CORS规范,允许跨域访问OBS中的资源,具体配置步骤请参见配置跨域资源共享。

CORS规则配置项建议:

表1 CORS规则

参数

说明

配置建议

允许的来源

必选参数,指定允许的跨域请求的来源,即允许来自该域名下的请求访问该桶。

允许多条匹配规则,以回车换行为间隔。每个匹配规则允许使用最多一个“*”通配符。例如:

http://rds.example.com
https://*.vbs.example.com

*

允许的方法

必选参数,指定允许的跨域请求方法,即桶和对象的几种操作类型。包括:Get、Post、Put、Delete、Head。

全选

允许的头域

可选参数,指定允许的跨域请求的头域。只有匹配上允许的头域中的配置,才被视为是合法的CORS请求。

允许的头域可设置多个,多个头域之间换行隔开,每行最多可填写一个*符号,不支持&、:、<、空格以及中文字符。

*

补充头域

可选参数,指CORS响应中带的补充头域,给客户端提供额外的信息。

补充头域可设置多个,多个头域之间换行隔开,不支持*、&、:、<、空格以及中文字符。

ETag
x-obs-request-id
x-obs-api
Content-Type
Content-Length
Cache-Control
Content-Disposition
Content-Encoding
Content-Language
Expires
x-obs-id-2
x-reserved-indicator
x-obs-version-id
x-obs-copy-source-version-id
x-obs-storage-class
x-obs-delete-marker
x-obs-expiration
x-obs-website-redirect-location
x-obs-restore
x-obs-version
x-obs-object-type
x-obs-next-append-position

缓存时间

必选参数,请求来源的客户端可以缓存的CORS响应时间,以秒为单位,默认为100秒。

根据实际业务设置。

配置小程序上传域名白名单。

微信小程序利用白名单机制管理跨域访问,想要实现数据上传,需要在微信小程序平台域名白名单中配置桶的访问域名。

获取桶的访问域名。

在桶列表单击待操作的桶,进入对象页面后单击“概览”。在“域名信息”下查看桶的访问域名。

图1 桶的访问域名

在微信小程序服务器域名配置中指定桶域名为合法域名。详细配置指导请在小程序客服搜索“服务器域名配置”,配置信息如表2所示。

图2 微信小程序配置服务器信息

表2 微信小程序配置建议

参数

配置建议

request合法域名

桶的访问域名

socket合法域名

根据实际情况填写

uploadFile合法域名

桶的访问域名

downloadFile合法域名

桶的访问域名

udp合法域名

根据实际情况填写

tcp合法域名

根据实际情况填写

计算POST上传签名。

POST上传前需要根据上传时自定义使用的policy字段计算相关签名信息,签名计算规则请参见基于浏览器上传的表单中携带签名,计算签名相关源代码如下:

对policy进行base64编码(GetPolicy.js):

const Base64 = require('js-base64');

function getPolicyEncode(policy) {
  // 传入表单上传的policy字段,对policy进行Base64编码
  const encodedPolicy = Base64.encode(JSON.stringify(policy));
  return encodedPolicy;
}

module.exports = getPolicyEncode;

计算签名的源代码(GetSignature.js):

const Crypto = require('crypto-js');
const Base64 = require('js-base64');

function getSignature(policyEncoded, SecretKey){
  // 利用SK对Base64编码后的policy结果进行HMAC-SHA1签名计算
  const bytes = Crypto.HmacSHA1(policyEncoded, SecretKey);
  // 对计算结果进行Base64编码,得到最终的签名信息
  const signature = Crypto.enc.Base64.stringify(bytes);
  return signature;
}

module.exports = getSignature;

使用小程序直传数据至对象存储桶中。

基于3中得到的编码后的policy字段及signature字段,可以调用小程序中的上传接口,选择本地文件并上传。具体代码示例如下:

配置AK、SK、访问域名等信息的配置文件(Configuration.js):

使用永久访问秘钥(AK/SK)

// 指定OBS服务相关信息:AK,SK,EndPoint
var Configuration = {
  // 认证用的ak和sk硬编码到代码中或者明文存储都有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全;本示例以ak和sk保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量AccessKeyId和SecretKey。
  // 前端本身没有process对象,可以使用webpack类打包工具定义环境变量,就可以在代码中运行了。
  // 您可以登录访问管理控制台获取访问密钥AK/SK,获取方式请参见https://support.huaweicloud.com/usermanual-ca/ca_01_0003.html
  AccessKeyId: process.env.AccessKeyID,
  SecretKey: process.env.SecretAccessKey,
  EndPoint: 'https://your-test-bucket.obs.myhuaweicloud.com',         //完整的桶访问域名
};


module.exports = Configuration;

使用临时访问秘钥(AK/SK/securitytoken)

获取临时AK/SK和securitytoken的方法,请参见获取临时AK/SK和securitytoken。

// 指定OBS服务相关信息:AK,SK,SecurityToken,EndPoint
var Configuration = {
  // 认证用的ak和sk硬编码到代码中或者明文存储都有很大的安全风险,建议在配置文件或者环境变量中密文存放,使用时解密,确保安全;本示例以ak和sk保存在环境变量中为例,运行本示例前请先在本地环境中设置环境变量AccessKeyId和SecretKey。
  // 前端本身没有process对象,可以使用webpack类打包工具定义环境变量,就可以在代码中运行了。
  // 您可以登录访问管理控制台获取访问密钥AK/SK,获取方式请参见https://support.huaweicloud.com/usermanual-ca/ca_01_0003.html
  AccessKeyId: process.env.AccessKeyID,
  SecretKey: process.env.SecretAccessKey,
  SecurityToken: process.env.SecurityToken,        //securityToken
  EndPoint: 'https://your-test-bucket.obs.myhuaweicloud.com',         //完整的桶访问域名
};


module.exports = Configuration;

配置文件中传入的EndPoint应该为完整的桶访问域名,例如:https://bucketName.obs.myhuaweicloud.com,其中bucketName即小程序上传的目标桶名。

// 引入配置文件
const config = require('./Configuration.js');
// 引入policy编码计算方法
const getPolicyEncode = require('./getPolicy.js');
// 引入签名计算方法
const getSignature = require('./GetSignature.js');

const OBSupload = function (filePath){
  if(!filePath){
    wx.showToast({
      title: 'Invalid filePath',
      icon: 'Please re-select path',
    });
  }
  else{
    const fileName = 'testMiniprogram.jpg';   // 指定上传到OBS桶中的对象名    

    const OBSPolicy = {                   // 设定policy内容,policy规则定义可参考步骤3中的超链接签名计算规则文档
      "expiration": "2021-12-31T12:00:00.000Z",
      "conditions": [
        { "bucket": "your-test-bucket" },  // 桶名要和配置文件中endpoint中的桶名保持一致
        // { "x-obs-security-token": config.SecurityToken } // 如果是临时访问秘钥鉴权,必须设置该值
        { 'key': fileName }
      ]
    }

    const policyEncoded = getPolicyEncode(OBSPolicy);                    // 计算base64编码后的policy
    const signature = getSignature(policyEncoded, config.SecretKey);     // 计算signature

    wx.uploadFile({
      url: config.EndPoint,
      filePath: filePath,
      name: 'file',
      header: {
        'content-type': 'multipart/form-data; boundary=-9431149156168',
      },
      formData: {
        // 从配置文件中获取到的AK信息、计算得到的编码后policy及signature信息
        'AccessKeyID': config.AccessKeyId,
        'policy': policyEncoded,
        'signature': signature,
        'key': fileName,
        // "x-obs-security-token": config.SecurityToken, // 如果是临时访问秘钥鉴权,必须设置该值
      },

      success: function(res){
        console.log(res.statusCode);            //打印响应状态码
        if(res.statusCode=='204'){
          console.log('Uploaded successfully', res)
          wx.showToast({
            title: 'Uploaded successfully',
            icon: 'Success'
          });
        }
        else{
          console.log('Uploaded failed', res)
          wx.showToast({
            title: 'Uploaded failed',
            icon: 'Fail'
          });
        }
      },
      fail: function(e){
        console.log(e);
      }
    })

  }
}

module.exports = OBSupload;

相关操作

上传完成后,要获取对应对象的访问URL,请参见如何获取对象访问路径。

同意关联代理商云淘科技,购买华为云产品更优惠(QQ 78315851)

内容没看懂? 不太想学习?想快速解决? 有偿解决: 联系专家