封装代码
'use strict'//使用严格模式
const crypto = require('crypto');//加密模块
function Client(options) {
if (!(this instanceof Client))
return new Client(options);
Client.validate(options);
Client.initOptions(options);
}
Client.validate = (options,key)=> {
if (Client.inited===true){ return;}
if (!options||!options.accessKeySecret) {
throw new Error('accessKeySecret是必需的!');
}
for (let key in options){
if(options[key] === undefined){
throw new Error('参数配置中出现了未定义数据:'+key);
}
}
Client.inited=true;
};
Client.initOptions=(options)=>{
Client.prototype.originData=options;
let signData={
conditions:[
[
"content-length-range",0,1048576000
]
]
};
//初始化policy有效期
signData.expiration=new Date(Date.now()+(options.expires?options.expires:30)*1000);
signData.conditions=Object.assign(signData.conditions,options.conditions?options.conditions:[]);
Client.prototype.expirtion=signData.expiration;
Client.prototype.signDate=JSON.stringify(signData);
Client.prototype.key=options.accessKeySecret;
};
Client.prototype.signature=()=>{
let signBase64=new Buffer(Client.prototype.signDate).toString("base64");
let sha1= crypto.createHmac("SHA1",Client.prototype.key);
let signature=sha1.update(signBase64).digest('base64');
let result={
originData:Client.prototype.originData,
signatureData:Client.prototype.signDate,
policy:signBase64,
signature:signature,
expirtion:Client.prototype.expirtion
};
return result;
};
module.exports=Client;
测试代码
const router=require('koa-router')();
const uuidv4 = require('uuid/v4');
const accessKeyId="";
const accessKeySecret="";
const host="";
const sign=require('../test/AliOSSSignUtil');//上面的生成签名的文件
router.get("/oss",async(ctx,next)=>{
let res= new sign({accessKeySecret:accessKeySecret}).signature();
let result={
accessid:accessKeyId,//阿里OSS访问ID
policy:res.policy,//base64转码后的约束信息
signature:res.signature,//对policy使用访问密钥做SHA1加密的签名数据
dir:"user-dir",//存储目录
host:host,//阿里外网域名
expire:res.expirtion,//该证书过期时间
fileName:uuidv4()//文件名称
};
ctx.body=result;
ctx.response.set("Access-Control-Allow-Origin","*");
ctx.response.set("Access-Control-Allow-Credentials","true");
ctx.response.set("Access-Control-Allow-Methods","GET, POST, DELETE, PUT");
return;
});
module.exports=router;
测试页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>阿里文件上传测试页面</title>
</head>
<body>
<div style="width: 60%;margin-left: auto;margin-right: auto">
<div class="page-header success">
<p class=""><h1>阿里OSS文件上传后台签名授权<small>for alioss</small></h1></p>
</div>
<div class="panel panel-warning">
<div class="panel-heading">阿里OSS文件上传后台签名授权</div>
<div class="panel-body">
<div class="form-group">
<label for="fileInput">上传文件:</label>
<form id="fileForm" name="fileForm">
<input type="file" id="fileInput" class="btn btn-success">
</form>
</div>
<div class="form-inline" style="margin-top: 20px">
<div class="btn-group" data-toggle="buttons-radio" id="div_fileChannel">
<label class="btn btn-success">
<input type="radio" name="radio_fileChannel" value="default" checked>使用默认文件名称
</label>
<label class="btn btn-default">
<input type="radio" name="radio_fileChannel" value="random">使用随机数生成名称
</label>
<label class="btn btn-warning">
<input type="radio" name="radio_fileChannel" value="custom">自定义文件名称
</label>
</div>
</div>
<div style="margin-top: 10px">
<button id="submit" type="button" class="btn btn-primary" data-loading-text="Loading...">提交</button>
</div>
</div>
</div>
<div class="panel panel-success">
<div class="panel-heading">返回结果</div>
<div class="panel-body">
<span id="resultContent">
</span>
</div>
</div>
</div>
<!--JavaScript-->
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script src="alioss.js"></script>
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- 可选的 Bootstrap 主题文件(一般不用引入) -->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
</body>
</html>
测试页面对应的JS
/*
* 获取文件名称的方法
*
*/
var FileNameStrategy={
};
FileNameStrategy["default"]=()=>{
return "";
};
FileNameStrategy["random"]=()=>{
return "";
};
FileNameStrategy["custom"]=()=>{
return "";
};
/**
* 处理文件名称
* @type {{process: (function(*))}}
*/
var FileNameProcess={
process:(channel)=>{
FileNameStrategy[channel?channel:"default"]();
}
};
/**
* 全局变量
* @type {{Filename: *, hasFile: boolean, form: undefined, policy: undefined, expireTime: undefined, signDate: undefined}}
* @private
*/
var _g_params={
Filename:FileNameProcess.process(),//上传文件名称
hasFile:false,//是否包含文件
form:undefined,//提交的form表单数据
policy:undefined,//授权证明
expireTime:undefined,//超时时间
signDate:undefined,//签名数据
resultUrl:undefined//回调URL
};
/**
*
* 对外暴露的方法
* @constructor
*/
const Client=function () {
init();
};
//绑定各元素事件
let init=()=>{
/*
* 处理单选按钮,并修改全局变量值
*/
let radio=$("input[name=radio_fileChannel]");
radio.click(()=>{
FileNameProcess.process($("input[name=radio_fileChannel]:checked").val());
});
/*
* 处理文件处理
*/
let fileContent=$("#fileInput");
fileContent.on("change",()=>{
//var form=new FormData($("#fileForm")[0][0].files[0]);
_g_params.form=new FormData();
_g_params.hasFile=true;
});
/*
* 处理提交按钮
* 先判断是有文件.
* 提交时优先判断,是否缓存了policy,如果没有且超时,则请求后台,否则直接使用.
*
*/
let commit=$("#submit");
commit.click(()=>{
//校验文件
if (_g_params.hasFile!=true||!_g_params.form){
//提示错误
//调用初始化方法
return;
}
//校验是否有参数,如果没有,进行初始化
if(!_g_params.expireTime||_g_params.expireTime<=new Date().getTime()){
//请求后台接口,获取最新数据
$.ajax({
url:'http://192.168.1.160:3000/oss',
type:"GET",
async:false,
success:function (data) {
_g_params.signDate=data;
_g_params.expireTime=data.expire;
}
});
}
//初始化form表单数据,进行数据请求
formDataProcess();
//请求
$.ajax({
url:_g_params.signDate.host,
type:"POST",
data:_g_params.form,
processData:false, // 告诉jQuery不要去处理发送的数据
contentType:false, // 告诉jQuery不要去设置Content-Type请求头
cache: false,//设置为false将不会从浏览器缓存中加载请求信息
async: false,//发送同步请求
success:(data)=>{
_g_params.resultUrl=$(data).find('Location').text();
let imgContext="<span class='alert alert-info'>"+_g_params.resultUrl+"</span>";
let imgTxt='<img class="img-responsive center-block" src="'+_g_params.resultUrl+'"/>';
$("#resultContent").append(imgContext).append(imgTxt);
},
error:(data)=>{
console.info(data)
}
});
});
};
let formDataProcess=()=>{
//初始化请求头
let form=_g_params.form;
let data=_g_params.signDate;
form.append("key","user-dir/"+data.fileName+".jpeg");//文件名称
form.append("policy",data.policy);//生成的数据
form.append("OSSAccessKeyId",data.accessid);//id
form.append("success_action_status",201);//选择201,获取返回内容
form.append("Signature",data.signature);//签名
form.append("file",$("#fileForm")[0][0].files[0]);//追加文件内容
form.append('submit', "Upload to OSS");
};
$(()=>{
new Client();
});
阿里云官方文档地址
网友评论