微信小程序直传图片至阿里云OSS,signature通过后台服务器获取(不暴露OssAccessKeySecret)

部署运行你感兴趣的模型镜像

一背景:

《微信小程序 上传图片至阿里云OSS(支持多图片上传)》该文章已实现微信小程序图片直接上传至阿里云OSS。

但以上文章的OssAccessKeySecret是存储在微信小程序中的,本人希望实现把待签名的字符串传至服务器端,由服务器端返回签名,这样OssAccessKeySecret就不需要存储在微信小程序前端也不需要在网络传输。

阿里云OSS提供了PutObject和PostObject两API,两个API的认证签名方法是不一样的, wx.uploadFile只支持POST方法,所以只能采用PostObject进行图片上传,其它方式尝试一遍都行不通。

如下网址对于解决问题很有帮助:

《PostObject》

《在Header中包含签名》

《在URL中包含签名》

《签名构建CanonicalizedOSSHeaders的方法》

二、实现

1、config.js

var fileHost = "https://xxxx";//你的阿里云OSS地址  在你当前小程序的公众号后台的uploadFile 合法域名也要配上这个域名
var config = {
  uploadImageUrl: `${fileHost}`, // 默认存在根目录,可根据需求改
  ossBucketName: "xxxx",
  timeout: 10 //这个是上传文件时Policy的失效时间
};
module.exports = config

2、uploadFile.js

const env = require('config.js'); 
const base64 = require('base64.js');
const getHeadSignature= require('getHeadSignature.js');

/*
 *上传文件到阿里云oss
 *@param - filePath :图片的本地资源路径
 *@param - dir:表示要传到oss哪个目录下
 *@param - successc:成功回调
 *@param - failc:失败回调
 */
const uploadFile = function(filePath, dir, successc, failc) {
  if (!filePath || filePath.length < 9) {
    wx.showModal({
      title: '图片错误',
      content: '请重试',
      showCancel: false,
    })
    return;
  }

  console.log('上传图片.....');
  //图片名字 可以自行定义,     这里是采用当前的时间戳 + 150内的随机数来给图片命名的
  const aliyunFileKey = dir + "/" + new Date().getTime() + Math.floor(Math.random() * 150) + '.png';
  const aliyunServerURL = env.uploadImageUrl;//OSS地址,需要https 
  const policyBase64 = getPolicyBase64();

  var signatureCallback = function(signData) {
    const accessId = signData.accessKeyId;
    var signature = signData.signature;
    signature = signature.split(":")[1];
    console.log("accessId =" + accessId);
    console.log("signature =" + signature);

    wx.uploadFile({
      url: aliyunServerURL,//开发者服务器 url
      filePath: filePath,//要上传文件资源的路径
      name: 'file',//必须填file
      formData: {
        'key': aliyunFileKey,
        'policy': policyBase64,
        'OSSAccessKeyId': accessId,
        'signature': signature,
        'success_action_status': '200',
      },
      success: function(res) {
        if (res.statusCode != 200) {
          failc(new Error('上传错误:' + JSON.stringify(res)))
          return;
        }
        successc(aliyunServerURL +"/"+ aliyunFileKey);
      },
      fail: function(err) {
        err.wxaddinfo = aliyunServerURL;
        failc(err);
      },
    })
  };
  getHeadSignature(policyBase64,signatureCallback); //获取签名

}

const getPolicyBase64 = function () {
  let date = new Date();
  date.setHours(date.getHours() + env.timeout);
  let srcT = date.toISOString();
  const policyText = {
    "expiration": srcT, //设置该Policy的失效时间,超过这个失效时间之后,就没有办法通过这个policy上传文件了 
    "conditions": [
      ["content-length-range", 0, 20 * 1024 * 1024] // 设置上传文件的大小限制,5mb
    ]

  };
  console.log(policyText)
  const policyBase64 = base64.encode(JSON.stringify(policyText));
  return policyBase64;
}

module.exports = uploadFile;

3、getHeadSignature.js

const env = require('config.js'); //配置文件,在这文件里配置你的OSS keyId和KeySecret,timeout:87600;

const getHeadSignature = function (toSignatureStr,callback) {
  const app = getApp();
  wx.request({
    url: app.globalData.serviceUrlPrefix + '/knowbetter/oss/headsignature',
    method: 'GET',
    header: {
      'content-type': 'application/x-www-form-urlencoded'
    },
    data: {
      sessionId: app.globalData.sessionId,
      toSignatureStr: toSignatureStr
    },
    success: function (res) {
      var signData = res.data;
      if (callback)
        callback(signData);

    },
    fail: function (res) {
      app.handleError(res);
    }
  });

}

module.exports = getHeadSignature;

其中:app.globalData.serviceUrlPrefix + '/knowbetter/oss/headsignature,就是获取遵循《在Header中包含签名》签名的后台服务

 

4、/knowbetter/oss/headsignature 对应的后台服务核心实现:

@Override
	public Signature getHeadSignature(String toSignatureStr) throws Exception {
		byte[] hmacSha1 = HmacSha1Util.hmacSHA1Encrypt(secret, toSignatureStr);
		final Base64.Encoder encoder = Base64.getEncoder();
		String base64 = encoder.encodeToString(hmacSha1);
		String signatureStr = "OSS " + accessKeyId + ":" + base64;
		Signature signature = new Signature();
		signature.setAccessKeyId(accessKeyId);
		signature.setSignature(signatureStr);
		return signature;
	}
public class Signature {
	
	private String accessKeyId;
	private String signature;
	public String getAccessKeyId() {
		return accessKeyId;
	}
	public void setAccessKeyId(String accessKeyId) {
		this.accessKeyId = accessKeyId;
	}
	public String getSignature() {
		return signature;
	}
	public void setSignature(String signature) {
		this.signature = signature;
	}

}

 

public class HmacSha1Util {
	private static final String MAC_NAME = "HmacSHA1";
    private static final String ENCODING = "UTF-8";

    public static byte[] hmacSHA1Encrypt(String encryptKey,String encryptText) throws Exception {
        byte[] data = encryptKey.getBytes(ENCODING);
        // 根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称
        SecretKey secretKey = new SecretKeySpec(data, MAC_NAME);
        // 生成一个指定 Mac 算法 的 Mac 对象
        Mac mac = Mac.getInstance(MAC_NAME);
        // 用给定密钥初始化 Mac 对象
        mac.init(secretKey);

        byte[] text = encryptText.getBytes(ENCODING);
        // 完成 Mac 操作
        return mac.doFinal(text);
    }
}

三、调用

var uploadImage = require('../../../utils/aliyunoss/uploadFile.js'); 
addImages: function() {
    var that=this;
    var ossImageDirPath = this.generateOssImageDirPath();
    var chooseImagesCallback = function(tempFilePaths) {
      var nowTime = util.formatTime(new Date());

      //支持多图上传
      for (var i = 0; i < tempFilePaths.length; i++) {
        //显示消息提示框
        wx.showLoading({
          title: '上传中' + (i + 1) + '/' + tempFilePaths.length,
          mask: true
        })

        //上传图片
        //你的域名下的/cbb文件下的/当前年月日文件下的/图片.png
        //图片路径可自行修改
        uploadImage(tempFilePaths[i], ossImageDirPath ,
          function(imageUrl) {
            console.log("======上传成功图片地址为:", imageUrl);
            //做你具体的业务逻辑操作
        
           
            wx.hideLoading();
          },
          function(result) {
            console.log("======上传失败======", result);
            //做你具体的业务逻辑操作

            wx.showModal({
              title: '图片上传错误',
              content: '请重试',
              showCancel: false,
            });
            wx.hideLoading()
          }
        )
      }
    };
    this.chooseImages(chooseImagesCallback);
  },
  generateOssImageDirPath:function(){
    var userName="lilidan_13570081911";
    var communityName="qiaojihuayuan";
     return "house_sale_or_rent/house_images/"+userName+"/"+communityName+"/"+this.data.infoId
  },
  chooseImages: function(callback) {
    wx.chooseImage({
      count: 9, // 默认最多一次选择9张图
      sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
      sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
      success: function(res) {
        // 返回选定照片的本地文件路径列表,tempFilePath可以作为img标签的src属性显示图片
        var tempFilePaths = res.tempFilePaths;
        callback(tempFilePaths);
      }
    })
  },

 

您可能感兴趣的与本文相关的镜像

GPT-oss:20b

GPT-oss:20b

图文对话
Gpt-oss

GPT OSS 是OpenAI 推出的重量级开放模型,面向强推理、智能体任务以及多样化开发场景

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值