服务端签名后直传(上传文件到oss)

demo的环境:idea2.6+Tomcat8+vue

我这边只是做了上传图片的demo,下面先看下所需依赖:

jetty-servlet:9.2.10.v20150310
jetty-servlets:9.2.10.v20150310
aliyun-sdk-oss:2.0.6
aliyun-java-sdk-sts:2.1.6
aliyun-java-sdk-core:2.1.7

commons-httpclient:3.1-rc1

guava:r09-jarjar
hadoop-streaming:2.6.0-mr1-cdh5.5.0
commons-codec:1.9

服务端签名后直传(上传文件到oss)

因为我这边开的是两个tomcat,所以不能同时占用一个端口,所以就设置了一下端口:

服务端签名后直传(上传文件到oss)

然后就是设置需要请求的阿里云服务端:

@WebServlet(asyncSupported = true)
public class PostObjectPolicy extends HttpServlet{
   /**
    * 
    */
   private static final long serialVersionUID = 5522372203700422672L;

   protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
   
       String endpoint = "oss-cn-shanghai.aliyuncs.com";
        String accessId = "LTAInnu3TavG4hjj";
        String accessKey = "WOL9xZ1pq8abRDNfDqbSOXZBshQNbK";
        String bucket = "*******";//服务端名称
        String dir = "images/";//上传到制定文件夹
        String host = "http://" + bucket + "." + endpoint;//请求路径
        OSSClient client = new OSSClient(endpoint, accessId, accessKey);
        try {  
           long expireTime = 30;
           long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            String postPolicy = client.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = client.calculatePostSignature(postPolicy);
            
            Map<String, String> respMap = new LinkedHashMap<String, String>();
            respMap.put("accessid", accessId);
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);
            //respMap.put("expire", formatISO8601Date(expiration));
            respMap.put("dir", dir);
            respMap.put("host", host);
            respMap.put("expire", String.valueOf(expireEndTime / 1000));
            JSONObject ja1 = JSONObject.fromObject(respMap);
            System.out.println(ja1.toString());
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "GET, POST");
            response(request, response, ja1.toString());
            
        } catch (Exception e) {
            e.printStackTrace();
//            Assert.fail(e.getMessage());
        }
    }
   
   private void response(HttpServletRequest request, HttpServletResponse response, String results) throws IOException {
      String callbackFunName = request.getParameter("callback");
      if (callbackFunName==null || callbackFunName.equalsIgnoreCase(""))
         response.getWriter().println(results);
      else
         response.getWriter().println(callbackFunName + "( "+results+" )");
      response.setStatus(HttpServletResponse.SC_OK);
        response.flushBuffer();
   }
   
   protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
      doGet(request, response);
    }
}

接下来直接运行上面的main方法就能拿到定好的端口号

我这边是在vue中进行上传的

下面这是我的上传界面以及代码

服务端签名后直传(上传文件到oss)


<template >
 <div class="page">
     <div class="handle-box">
        <el-row type="flex" class="row-bg" justify="flex-start">
            <el-button type="primary" icon="back" @click="back">确定</el-button>
<el-button type="primary"  icon="back" @click="aa">测试</el-button>
            <!--<el-button :type="isFrozen == 1 ? 'danger' : 'success'" @click="isFrazon" v-text="frazonTip"></el-button>-->
        </el-row>
    </div>
    <div class="content_info">
<el-form ref="form" :model="form" label-width="100px">
<el-form-item label="用户头像:">
<div id="container">
<div id="ossfile"></div>
<a id="selectfiles" href="javascript:void(0);" class='btn'>选择文件</a>
<a id="postfiles" href="javascript:void(0);" class='btn'>开始上传</a>
</div>
</el-form-item>


</el-form>
    </div>
 </div>
</template>
<script type="text/ecmascript-6">
import qs from 'qs'
  export default {
        data() {
            return {
                form: {
                },
g_object_name : '',
key:'',
accessid : '',
accesskey : '',
host : '',
policyBase64 : '',
signature : '',
callbackbody :'',
filename : '',
g_object_name_type:'local_name',
new_multipart_params:'',
suffix:'',
uid:'',
                tooltip: true,
                authority: false, //操作权限的显示控制
                titleStatus: true,
            };
        },     
       created() {
},

methods: {

                //上传的时候用uuid对图片名进行了处理

UUID:function() {

var s = [];
var hexDigits = "0123456789abcdef";
for (var i = 0; i < 36; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[14] = "4"; 
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); 

s[8] = s[13] = s[18] = s[23] = "-";
                 var uuid = s.join("");
return uuid;
},
//计算对象名称
calculate_object_name:function(filename){
if (this.g_object_name_type == 'local_name'){
this.g_object_name += "${filename}";
}
else if (this.g_object_name_type == 'random_name'){
this.suffix = this.get_suffix(filename);
this.g_object_name = this.key + random_string(10) + this.suffix;
}
return '';
},
//设置上传参数
set_upload_param:function(up,filename, ret){
if (ret == false)
{
ret = this.get_signature();
}
this.g_object_name = this.key;
if (filename != '') {
var uuid=filename.split('.');
this.uid=this.UUID()+"."+uuid[1];
this.filename=this.uid;
this.suffix = this.get_suffix(this.filename);
this.calculate_object_name(this.filename);
this.g_object_name = this.get_uploaded_object_name(this.g_object_name);

}
this.new_multipart_params = {
'key' : this.g_object_name,
'policy': this.policyBase64,
'OSSAccessKeyId': this.accessid, 
'success_action_status' : '200', //让服务端返回200,不然,默认会返回204
'callback' : this.callbackbody,
'signature': this.signature,
};
up.setOption({
'url': this.host,
'multipart_params': this.new_multipart_params
});


up.start();

},

//发送请求
send_request:function(){
var xmlhttp = null;
if (window.XMLHttpRequest){
xmlhttp=new XMLHttpRequest();
}
else if (window.ActiveXObject){
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}  
if (xmlhttp!=null)
{
var serverUrl = 'http://127.0.0.1:7090' ;
xmlhttp.open( "GET", serverUrl, false );
xmlhttp.send( null );
return xmlhttp.responseText;
}else{
alert("Your browser does not support XMLHTTP.");
}
},
//得到签名
get_signature:function(){
var expire =0;
var timestamp=null;
//可以判断当前expire是否超过了当前时间,如果超过了当前时间,就重新取一下.3s 做为缓冲
var now = timestamp = Date.parse(new Date()) / 1000; 
if (expire < now + 3){
var body = this.send_request();
var obj = eval ("(" + body + ")");
this.host = obj['host'];
this.policyBase64 = obj['policy'];
this.accessid = obj['accessid'];
this.signature = obj['signature'];
expire = parseInt(obj['expire']);
this.callbackbody = obj['callback'] ;
this.key = obj['dir'];
return true;
}
return false;
},
//得到后缀
get_suffix:function(filename) {
var pos = filename.lastIndexOf('.')
//var suffix = ''
if (pos != -1) {
this.suffix = filename.substring(pos)
}
return this.suffix;
},
//得到上传对象名称
get_uploaded_object_name:function(filename){
if (this.g_object_name_type == 'local_name'){
var tmp_name = this.g_object_name;
tmp_name = tmp_name.replace("${filename}", this.uid);
return tmp_name;
}
else if(this.g_object_name_type == 'random_name'){
return this.g_object_name;3w
}
},
aa:function(){
  var _this = this ;
  var uploader = new plupload.Uploader({
runtimes : 'html5,flash,silverlight,html4',
browse_button : 'selectfiles', 
//multi_selection: false,
container: document.getElementById('container'),
flash_swf_url : 'lib/plupload-2.1.2/js/Moxie.swf',
silverlight_xap_url : 'lib/plupload-2.1.2/js/Moxie.xap',
url : 'http://oss.aliyuncs.com',


filters: {
mime_types : [ //只允许上传图片和zip,rar文件
{ title : "Image files", extensions : "jpg,gif,png,bmp" }, 
{ title : "Zip files", extensions : "zip,rar" }
],
max_file_size : '10mb', //最大只能上传10mb的文件
prevent_duplicates : true //不允许选取重复文件
},


init: {
PostInit: function() {
document.getElementById('ossfile').innerHTML = '';
document.getElementById('postfiles').onclick = function() {
_this.set_upload_param(uploader, '', false);
return false;
};
},
//添加文件
FilesAdded: function(up, files) {
plupload.each(files, function(file) {
document.getElementById('ossfile').innerHTML += '<div id="' + file.id + '">' + file.name + ' (' + plupload.formatSize(file.size) + ')<b></b>'
+'<div class="progress"><div class="progress-bar" style="width: 0%"></div></div>'
+'</div>';
});
},
//上传之前
BeforeUpload: function(up, file) {
_this.check_object_radio();
_this.set_upload_param(up, file.name, true);
},
//上传进度
UploadProgress: function(up, file) {
var d = document.getElementById(file.id);
d.getElementsByTagName('b')[0].innerHTML = '<span>' + file.percent + "%</span>";
var prog = d.getElementsByTagName('div')[0];
var progBar = prog.getElementsByTagName('div')[0]
progBar.style.width= 2*file.percent+'px';
progBar.setAttribute('aria-valuenow', file.percent);
},
//文件上传
FileUploaded: function(up, file, info) {
if (info.status == 200){
_this.filename=_this.uid;
document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = 'upload to oss success, object name:' + _this.get_uploaded_object_name(_this.filename);
}
else{
document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = info.response;

},


Error: function(up, err) {
if (err.code == -600) {
document.getElementById('console').appendChild(document.createTextNode("\n选择的文件太大了,可以根据应用情况,在upload.js 设置一下上传的最大大小"));
}
else if (err.code == -601) {
document.getElementById('console').appendChild(document.createTextNode("\n选择的文件后缀不对,可以根据应用情况,在upload.js进行设置可允许的上传文件类型"));
}
else if (err.code == -602) {
document.getElementById('console').appendChild(document.createTextNode("\n这个文件已经上传过一遍了"));
}
else 
{
document.getElementById('console').appendChild(document.createTextNode("\nError xml:" + err.response));
}
}
}
});


uploader.init();
}
 
}
 }
</script>


<style scoped>
.avatar-uploader .el-upload {
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
  }
  .avatar-uploader .el-upload:hover {
    border-color: #409EFF;
  }
  .avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    line-height: 178px;
    text-align: center;
  }
  .avatar {
    width: 178px;
    height: 178px;
    display: block;
  }
.handle-box{
    margin-bottom: 20px;
}
.handle-select{
    width: 120px;
}
.handle-input{
    width: 300px;
    display: inline-block;
}
.userbox {
    height: 100px;
    line-height: 100px;
    margin-bottom: 20px;
}
.userbox img {
    width: 100px;
    height: 100px;
    overflow: hidden;
    border-radius: 10px;
vertical-align: middle;
}
li {
    height: 36px;
}

</style>

这边需要注意的点就是需要一个必须的js文件,放在vue的起始界面就好

<script type=text/javascript src=./static/js/plupload.full.min.js></script>

还有就是必须先点击测试才能选择文件,这里换了几种方法没解决好,后续会改进

效果图:

服务端签名后直传(上传文件到oss)

服务端签名后直传(上传文件到oss)