天天看點

【OSS】支付寶小程式直傳OSS實踐

步驟1:配置Bucket跨域通路

用戶端進行表單直傳到OSS時,會從浏覽器向OSS發送帶有Origin的請求消息。OSS對帶有Origin頭的請求消息會進行跨域規則(CORS)的驗證。是以需要為Bucket設定跨域規則以支援Post方法。

  1. 登入 OSS管理控制台
  2. 單擊Bucket清單,之後單擊目标Bucket名稱。
  3. 單擊權限管理 > 跨域設定,在跨域設定區域單擊設定。
  4. 單擊建立規則,配置如下圖所示。
【OSS】支付寶小程式直傳OSS實踐
說明 為了您的資料安全,實際使用時,來源建議填寫實際允許通路的域名。更多配置資訊請參見 設定跨域通路

步驟2:擷取簽名

為了您的資料安全,建議使用簽名方式上傳檔案。OSS提供以下兩種簽名方式的代碼:

  • 服務端簽名使用服務端簽名時,您需要先搭建一個簽名服務,之後由用戶端調用簽名服務生成簽名。
    • 服務端簽名源碼uploadOssHelper.js代碼如下:
const crypto = require("crypto-js");
class MpUploadOssHelper {
  constructor(options) {
    this.accessKeyId = options.accessKeyId;
    this.accessKeySecret = options.accessKeySecret;
    this.timeOut = options.timeout || 1; // 限制參數的生效時間(機關:小時)。
    this.maxSize = options.maxSize || 10; // 限制上傳檔案大小(機關:Mb)。
  }
  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();
    const policyText = {
      expiration: srcT,
      conditions: [
        // 限制上傳檔案大小。
        ["content-length-range", 0, this.maxSize * 1024 * 1024],
      ],
    };
    const buffer = new Buffer(JSON.stringify(policyText));
    return buffer.toString("base64");
  }
  signature(policy) {
    return crypto.enc.Base64.stringify(
      crypto.HmacSHA1(policy, this.accessKeySecret)
    );
  }
}
module.exports = MpUploadOssHelper;      
    • 服務端接口示例

以Express為例,接口代碼如下:

const express = require('express');
const app = express();
const MpUploadOssHelper = require("./uploadOssHelper.js");
app.get('/getPostObjectParams', (req, res) => {
  const mpHelper = new MpUploadOssHelper({
    accessKeyId: '<Your AccessKeyId>',
    accessKeySecret: '<Your AccessKeySecret>',
    timeout: 1, // 限制參數的生效時間(機關:小時)。
    maxSize: 10, // 限制上傳檔案大小(機關:Mb)。
  });
  // 生成參數。
  const params = mpHelper.createUploadParams();
  res.json(params);
})      

相關參數如下:

      • accessKeyId: 填寫您的AccessKey ID。擷取方式請參見 建立AccessKey
      • accessKeySecret: 填寫您的AccessKey Secret。擷取方式請參見
  • 用戶端簽名

使用用戶端簽名時,您需要先在服務端搭建一個STS服務,之後由用戶端擷取STS臨時授權賬号并生成簽名。

    • 服務端搭建STS服務
const OSS = require('ali-oss')
const STS = OSS.STS
const express = require('express');
const app = express();
const stsClient = new STS({
  accessKeyId: '<Your AccessKeyId>',
  accessKeySecret: '<Your AccessKeySecret>',
  bucket: '<Your bucket name>'
});
async function getToken() {
    const STS_ROLE = '<STS_ROLE>'  // 指定角色的ARN。格式:acs:ram::$accountID:role/$roleName。
    const STSpolicy = {
      Statement: [
        {
          Action: ['oss:*'],
          Effect: 'Allow',
          Resource: ['acs:oss:*:*:*']
        }
      ],
      Version: '1'
    };
    const result = await stsClient.assumeRole(
      STS_ROLE,
      STSpolicy,
      3600 // STS過期時間,機關:秒。
    );
    const { credentials } = result;
    return credentials;
}
app.get('/getToken', async (req, res) => {
  // 擷取STS。
  const credentials = await getToken()
  console.log(credentials.AccessKeyId)
  console.log(credentials.AccessKeySecret)
  console.log(credentials.SecurityToken)
  res.json(credentials);
})      
    • 用戶端擷取STS臨時賬号并生成簽名
import crypto from 'crypto-js';
import { Base64 } from 'js-base64';
// 計算簽名。
function computeSignature(accessKeySecret, canonicalString) {
  return crypto.enc.Base64.stringify(crypto.HmacSHA1(canonicalString, accessKeySecret));
}
const date = new Date();
date.setHours(date.getHours() + 1);
const policyText = {
  expiration: date.toISOString(), // 設定policy過期時間。
  conditions: [
    // 限制上傳大小。
    ["content-length-range", 0, 1024 * 1024 * 1024],
  ],
};
async function getFormDataParams() {
  const credentials = await axios.get('/getToken')
  const policy = Base64.encode(JSON.stringify(policyText)) // policy必須為base64的string。
  const signature = computeSignature(credentials.AccessKeySecret, policy)
  const formData = {
    OSSAccessKeyId: credentials.AccessKeyId,
    signature,
    policy,
    'x-oss-security-token': credentials.SecurityToken 
  }
  return formData
}      

步驟3:使用支付寶小程式上傳

支付寶小程式上傳檔案參考代碼如下:

const host = '<host>';
const signature = '<signatureString>';
const ossAccessKeyId = '<accessKey>'; 
const policy = '<policyBase64Str>';
const securityToken = '<x-oss-security-token>';
const key = '<object name>'
my.chooseImage({
  chooseImage: 1,
  success: res => {
    const path = res.apFilePaths[0];
    my.uploadFile({
        url: host,
        fileType: 'image',
        fileName: 'file',
        filePath: path,
        formData: {
            key,
            policy,
            OSSAccessKeyId: ossAccessKeyId,
            signature,
            success_action_status: '200',
            // 'x-oss-security-token': securityToken // 使用STS簽名時必傳。
        },
        success: (res) => {
          // 預設上傳成功狀态碼為204,此處被success_action_status設定為200。
          if (res.statusCode === 200) {
            console.log('上傳成功');
          }
          my.alert({ content: 'success info: ' + res.data });
        },
        fail: err => {
          console.log(err);
        }
    });
  }
});      
  • host:填寫存儲空間的通路域名,例如 https://test.oss-cn-zhangjiakou.aliyuncs.com 。若您的存儲空間已綁定自定義域名,建議填寫您的自定義域名。
  • signature:填寫 步驟2 中擷取到的signature資訊。
  • ossAccessKeyId:填寫您的AccessKey ID,若是通過STS擷取的臨時使用者,則填寫臨時使用者的AccessKey ID。
  • policy:填寫 中擷取到的policy資訊。
  • key:設定檔案上傳至OSS後的檔案路徑。例如需要将myphoto.jpg上傳至test檔案夾下,此處填寫test/myphoto.jpg。
  • securityToken:若使用STS認證,此項填寫用戶端簽名時擷取到的SecurityToken。