鉴于安全性,本文采用的是服务端签名后直传方式。
本文分为两部分讲解:
服务端签名后直传 — 官方文档
上传中使用了 plupload. 详见plupload官方文档
阿里云 JavaScript客户端签名直传 官方文档
本文中的代码是经过删改过后的代码,若想看完整的具体代码,请点击:
阿里官方客户端代码 下载
// html部分
<div id="upload-container">
<div id="upload-monitor">
<span>上传</span>
</div>
</div>
// 代码中使用的Base64、Crypto、plupload在官方客户端代码中均有
var fileName = ''; // 上传的文件名称。可以使用原本的文件名称,也可以使用随机的文件名(自由发挥)
var accessid = ''; // 记录请求后端接口获取到的阿里的accessid
var accesskey = ''; // 记录请求后端接口获取到的阿里的accesskey
var token = ''; // 记录请求后端接口获取到的阿里的token
var host = 'http://xxx.xxx.aliyuncs.com'; // OSS访问域名
var policyBase64 = ''; // 上传文件时所需要的policy
var signature = ''; // 签名
var uploadConfig = {
}; // 定义的上传的配置对象
// 获取阿里token等相关信息的方法
function getToken(){
}
getToken().then(function(res){
if(res.success){
// (这个看后端返回的字段名叫什么,此处是随便一写~)
accessid = res.accessid;
accesskey = res.accesskey;
token = res.token;
var policyText = {
//设置该Policy的失效时间,超过这个失效时间之后,就没有办法通过这个policy上传文件了
'expiration': res.expiration,
'conditions': [
['content-length-range', 0, 1048576000] // 设置上传文件的大小限制
]
};
policyBase64 = Base64.encode(JSON.stringify(policyText));
var message = policyBase64;
var bytes = Crypto.HMAC(Crypto.SHA1, message, accesskey, {
asBytes: true }) ;
signature = Crypto.util.bytesToBase64(bytes);
// 定义plupload的init方法
var eventConfig = function(){
return {
'FilesAdded': function(up, files){
setTimeout(function(){
up.start();
}, 0);
},
'BeforeUpload': function(up, file){
set_upload_param(up, file.name, true);
},
'UploadProgress': function (up, file) {
},
'FileUploaded': function(up, file, info){
},
'Error': function(up, err, errTip){
switch(err.code) {
case -602:
ZhMsg = '这个文件已经上传过一遍了';
break;
case -600:
ZhMsg = '上传文件过大,大小不能超过:xxx';
break;
case -601:
ZhMsg = '请上传指定格式的文件';
break;
default:
ZhMsg = '未知错误';
break;
}
}
var filters = uploadConfig.filter; // 对上传文件的限制(类型,大小等)
var multi_selection = uploadConfig.multi_selection; //
var upload2ALi = new plupload.Uploader({
runtimes: 'html5,flash,html4',
browse_button: 'upload-monitor',
container: 'upload-container',
flash_swf_url: './Moxie.swf',
url: 'http://oss.aliyuncs.com',
filters: filters || {
},
multi_selection: multi_selection,
dragdrop: true,
drop_element: 'upload-monitor',
init: eventConfig()
});
upload2ALi.init();
};
};
}
});
// 设置上传的参数
function set_upload_param(up, filename, ret){
fileName = 'xxx'; // 设置上传文件的名称
var new_multipart_params = {
'key': fileName,
'policy': policyBase64,
'OSSAccessKeyId': accessid,
'x-oss-security-token': token,
'success_action_status': '200', //让服务端返回200,不然,默认会返回204
'signature': signature
};
up.setOption({
'url': host,
'multipart_params': new_multipart_params
});
// 开始上传
up.start();
}
// 获取上传文件的后缀 在文件名称中根据实际需要可能会用到。本文中没有使用
function get_suffix(filename) {
var pos = filename.lastIndexOf('.');
var suffix = '';
if (pos != -1) {
suffix = filename.substring(pos);
}
return suffix;
}
}
另外的补充:
// 上传也可以指定具体的文件夹。指定后在set_upload_param函数中的key的前面加上路径即可
var g_dirname = "abc/";
var new_multipart_params = {
'key': g_dirname + fileName,
...
};
// 如果希望上传后保持原来的文件名,则
var new_multipart_params = {
'key': g_dirname + '${filename}',
...
};
小程序中提供了上传的API: wx.uploadfile() 详细介绍见官方文档
// config为文件相关信息
// 如上传录音:
RecorderManager.onStop(res => {
uploadToAli({
filePath: res.tempFilePath});
});
function uploadToAli(config){
var filePath = config.filePath; // 文件路径
if(!filePath){
// 如果不存在则上传错误
console.log('上传参数有误');
}
var accessid = '';
var accesskey = '';
var token = '';
wx.request({
method: 'GET',
url: 'xxx' // 请求阿里token等信息的接口
}).then(function(res){
accessid = res.accessid;
accesskey = res.accesskey;
token = res.token;
var policyText = {
'expiration': res.expiration,
'conditions': [
['content-length-range', 0, 1048576000] // 设置上传文件的大小限制
]
};
var policyBase64 = Base64.encode(JSON.stringify(policyText));
var message = policyBase64;
var signature = '';
var bytes = wx.Crypto.HMAC(wx.Crypto.SHA1, message, accesskey, {
asBytes: true }) ;
signature = wx.Crypto.util.bytesToBase64(bytes);
wx.uploadFile({
filePath: config.filePath,
url: 'http://xxx.xxx.aliyuncs.com', // OSS域名
name: 'file',
formData: {
key: '${filename}',
policy: policyBase64,
OSSAccessKeyId: accessid,
'x-oss-security-token': token,
success_action_status: '200', //让服务端返回200,不然,默认会返回204
signature: signature
},
error: function(error){
consle.log('上传有误');
}
});
});
}