一背景:
《微信小程序 上传图片至阿里云OSS(支持多图片上传)》该文章已实现微信小程序图片直接上传至阿里云OSS。
但以上文章的OssAccessKeySecret是存储在微信小程序中的,本人希望实现把待签名的字符串传至服务器端,由服务器端返回签名,这样OssAccessKeySecret就不需要存储在微信小程序前端也不需要在网络传输。
阿里云OSS提供了PutObject和PostObject两API,两个API的认证签名方法是不一样的, wx.uploadFile只支持POST方法,所以只能采用PostObject进行图片上传,其它方式尝试一遍都行不通。
如下网址对于解决问题很有帮助:
《签名构建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);
}
})
},

8万+

被折叠的 条评论
为什么被折叠?



