- 2015-10-26
- angularjs結合aliyun瀏覽器端oos文件上傳加臨時身份驗證例子
- 在服務端獲取sts
源碼:
public class StsServiceSample { // 目前只有"cn-hangzhou"這個region可用, 不要使用填寫其他region的值 //<setting name="accessKeyId" value="H6JSh0Y****z2cGa" /> //<setting name="ecretAccessKey" value="0joCPK6L1S0KLxC***3wulC7vG" /> public static final String REGION_CN_HANGZHOU = "cn-hangzhou"; // 當前 STS API 版本 public static final String STS_API_VERSION = "2015-04-01"; static AssumeRoleResponse assumeRole(String accessKeyId, String accessKeySecret, String roleArn, String roleSessionName, String policy, ProtocolType protocolType) throws ClientException { try { // 創建一個 Aliyun Acs Client, 用於發起 OpenAPI 請求 IClientProfile profile = DefaultProfile.getProfile(REGION_CN_HANGZHOU, accessKeyId, accessKeySecret); DefaultAcsClient client = new DefaultAcsClient(profile); // 創建一個 AssumeRoleRequest 並設置請求參數 final AssumeRoleRequest request = new AssumeRoleRequest(); request.setVersion(STS_API_VERSION); request.setMethod(MethodType.POST); request.setProtocol(protocolType); request.setRoleArn(roleArn); request.setRoleSessionName(roleSessionName); request.setPolicy(policy); // 發起請求,並得到response final AssumeRoleResponse response = client.getAcsResponse(request); return response; } catch (ClientException e) { throw e; } } /** * @param args */ /** * @param args */ public static void main(String[] args) { // 只有 RAM用戶(子賬號)才能調用 AssumeRole 接口 // 阿里雲主賬號的AccessKeys不能用於發起AssumeRole請求 // 請首先在RAM控制台創建一個RAM用戶,並為這個用戶創建AccessKeys // 參考:https://docs.aliyun.com/#/pub/ram/ram-user-guide/user_group_management&create_user String accessKeyId = "G8dGVL***AwWWxX3"; String accessKeySecret = "nmha7GAObJE1tF***RbqEB5TYU1ScK"; // AssumeRole API 請求參數: RoleArn, RoleSessionName, Polciy, and DurationSeconds // 參考: https://docs.aliyun.com/#/pub/ram/sts-api-reference/actions&assume_role // RoleArn 需要在 RAM 控制台上獲取 // 參考: https://docs.aliyun.com/#/pub/ram/ram-user-guide/role&user-role String roleArn = "acs:ram::30150***706:role/lium"; // RoleSessionName 是臨時Token的會話名稱,自己指定用於標識你的用戶,主要用於審計,或者用於區分Token頒發給誰 // 但是注意RoleSessionName的長度和規則,不要有空格,只能有'-' '_' 字母和數字等字符 // 具體規則請參考API文檔中的格式要求 String roleSessionName = "lium"; // 如何定制你的policy? // 參考: https://docs.aliyun.com/#/pub/ram/ram-user-guide/policy_reference&struct_def // OSS policy 例子: https://docs.aliyun.com/#/pub/oss/product-documentation/acl&policy-configure // OSS 授權相關問題的FAQ: https://docs.aliyun.com/#/pub/ram/faq/oss&basic String policy = "{\n" + " \"Version\": \"1\", \n" + " \"Statement\": [\n" + " {\n" + " \"Action\": [\n" + " \"oss:GetBucket\", \n" + //此處表示對於myBucket的只能進行獲取操作,若想進行更多操作將GetBucket改為*即可,否則會拒絕訪問 " \"oss:GetObject\" \n" + //此處表示對於myBucket下的文件夾project的只能進行獲取操作,若想進行更多操作將GetObject改為*即可,否則會拒絕訪問 " ], \n" + " \"Resource\": [\n" + " \"acs:oss:*:30150***706:myBucket\", \n" + //此處數字必須與RoleArn中的數字一直 " \"acs:oss:*:30150***706:myBucket/project/*\" \n" + " ], \n" + " \"Effect\": \"Allow\"\n" + " }\n" + " ]\n" + "}"; // 此處必須為 HTTPS ProtocolType protocolType = ProtocolType.HTTPS; try { final AssumeRoleResponse response = assumeRole(accessKeyId, accessKeySecret, roleArn, roleSessionName, policy, protocolType); System.out.println("Expiration: " + response.getCredentials().getExpiration()); System.out.println("Access Key Id: " + response.getCredentials().getAccessKeyId()); System.out.println("Access Key Secret: " + response.getCredentials().getAccessKeySecret()); System.out.println("Security Token: " + response.getCredentials().getSecurityToken()); System.out.println("RequestId: "+response.getRequestId()); } catch (ClientException e) { System.out.println("Failed to get a token."); System.out.println("Error code: " + e.getErrCode()); System.out.println("Error message: " + e.getErrMsg()); } } }
注意:這是maven工程需要在pom.xml文件中引入以下內容:
<!-- 阿里雲STS -->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-sts</artifactId>
<version>2.1.6</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>2.1.7</version>
</dependency>
最后將所需要的參數拼成json字符串,發送到前端即可,json例子如下:
- 前端js獲取sts且添加工具包oss-js-upload.js和aliyun-sdk-js.js,詳情請參考以下網址https://github.com/aliyun-UED/oss-js-upload ;https://github.com/aliyun-UED/aliyun-sdk-js,請詳細閱讀README.md文件;
源碼:
/** * 取得stsToken */ $scope.getStsToken = function () { var qqslResource = $resource(httpUrl + 'oss/sts', {}, actions); qqslResource.get({}, function (data) { // 實例化上傳對象 $scope.ossUpload = new OssUpload({ bucket: 'qqsl', // 根據你的 oss 實例所在地區選擇填入 endpoint: 'http://oss-cn-hangzhou.aliyuncs.com', // 如果文件大於 chunkSize 則分塊上傳, chunkSize 不能小於 100KB 即 102400 chunkSize: 1048576, // 分塊上傳的並發數 concurrency: 2, // 注意: 雖然使用 accessKeyId 和 secretAccessKey 可以進行上傳, 但是存在泄露風險, 因此強烈建議使用下面的 STS token // 只有在確認不會出現泄露風險的情況下, 才使用 aliyunCredential stsToken: data }); }); }; // 建立上傳文件信息 $scope.makeOptions = function (files, index) { var data = { // 必傳參數, 需要上傳的文件對象 file: files[index], // 必傳參數, 文件上傳到 oss 后的名稱, 包含路徑 key: "project/" + $scope.unit.treePath + "/" + files[index].name, // 上傳失敗后重試次數 maxRetry: 2, // OSS支持4個 HTTP RFC2616(https://www.ietf.org/rfc/rfc2616.txt)協議規定的Header 字段: // Cache-Control、Expires、Content-Encoding、Content-Disposition。 // 如果上傳Object時設置了這些Header,則這個Object被下載時,相應的Header值會被自動設置成上傳時的值 // 可選參數 headers: { 'CacheControl': 'public', 'Expires': '', 'ContentEncoding': '', 'ContentDisposition': '', // oss 支持的 header, 目前僅支持 x-oss-server-side-encryption 'ServerSideEncryption': '' }, // 文件上傳失敗后調用, 可選參數 onerror: function (evt) { console.log(evt); }, // 文件片上傳事件 onprogress: function (loaded, total, res) { $scope.onprogress(files, loaded, total, res); }, // 文件上傳成功調用, 可選參數 oncomplete: function (res) { $scope.oncomplete(files, res); } }; return data; }; // 分片上傳事件 $scope.onprogress = function (files, loaded, total, res) { var fileName = res.key.substring(res.key.lastIndexOf("\/") + 1); console.log(loaded, total, (loaded / total * 100).toFixed(1)); var progress = (loaded / total * 100).toFixed(0); for (var i = 0; i < files.length; i++) { if (files[i].name == fileName) { files[i].progress = parseInt(progress); // 立即更新數據 $scope.$apply(); break; } } }; // 文件上傳成功事件 $scope.oncomplete = function (files, res) { // 更新文件列表 $scope.queryObjectFiles($scope.unit.id); if (res.Key) { // 大文件 for (var i = 0; i < files.length; i++) { var fileName = res.Key.substring(res.Key.lastIndexOf("\/") + 1); if (files[i].name == fileName) { files.splice(i, 1); break; } } } if (res.Key == undefined) { $scope.uploadSum++; } if ($scope.uploadSum >= files.length) { files.splice(0, files.length); } }; // 多文件上傳 $scope.isdrop = false; $scope.uploadFiles = function (files) { if (files == undefined || files == null || files.length == 0) { $scope.isupload=true; $scope.setMsg('請拖拽要上傳的文件!'); return; } if (files.length > 10) { $scope.isupload=true; $scope.setMsg('最多一次性上傳10個文件!'); return; } var fileLength = files.length; $scope.uploadSum = 0; for (var i = 0; i < files.length; i++) { var name = files[i].name; console.log(name.substring(name.lastIndexOf("\.") + 1)); for(var w = 0;w < $scope.editGridOptions.data.length;w++){ if($scope.editGridOptions.data[w].size==files[i].size&& $scope.editGridOptions.data[w].name==files[i].name) { files.splice(i, 1); } } // 小於36M的office文件上傳到后台 if (files[i].size < 36 * 1024 * 1024 && $scope.toPdf.indexOf(name.substring(name.lastIndexOf("\.") + 1)) != -1) { $scope.serverUpload($scope.unit.id, files[i]); } // 上傳到阿里雲oss $scope.ossUpload.upload($scope.makeOptions(files, i)); } }; /** * 自動檢測上傳的文件數目並刪除重復文件 * @param files */ $scope.change = function(files){ var result = [], hash = {},elem, i,name; if(files.length>10) { $scope.isupload = true; $scope.setMsg('最多一次性上傳10個文件!'); files.splice(10); console.log(files); return; } for(var i=0;i<files.length;i++){ for(var j=i+1;j<files.length;){ //后面的元素若和待比較的相同,則刪除並計數; //刪除后,后面的元素會自動提前,所以指針j不移動 if(files[j].name==files[i].name&&files[j].size==files[i].size){ $scope.isupload=true; name = files[i].name.length<10?files[i].name:files[i].name.substring(0,10)+".."; $scope.setMsg('已刪除重復文件:'+name); files.splice(j,1); }else{ j++; } //不同,則指針移動 } } }; /** * 刪除已拖拽的文件 * @param name * @param file * @returns {*} */ $scope.deleteFile = function (name, files) { console.log(name); for (var i = 0; i < files.length; i++) { if (files[i].name == name) { files.splice(i, 1) } } //$scope.isupload==false; $scope.change(files); console.log(files); return files; };
在頁面中使用ng-file-upload插件,此插件支持拖拽上傳,累加拖拽,限制上傳文件的格式以及大小,也有進度條插件。如果要顯示進度條,必須要修改oss-file-upload源碼才行。
思路:頁面用ng-file-upload插件,使用它提供的一些拖拽等功能,在js中將ng-file-upload的upload函數替換為oss中的upload對象即可,提供此對象所需要的參數即可。
頁面源碼:
<!-- 文件列表 --> <div class="clear col-lg-12" ng-if="unit.type=='DIRCTORY'"> <div class="info-space"> <p class="text-left lead">文件列表</p> </div> <div class="clear"> <table ui-grid="editGridOptions" ui-grid-auto-resize class="ui-grid" ng-style="getTableHeight()"></table> </div> <div class="clear info-space"> <form name="fileForm"> <!-- 上傳 --> <div class="col-lg-6">拖拽文件:</div> <div class="col-lg-8"> <div ngf-drop ng-model="files" class="drop-box" ngf-drag-over-class="dragover" ngf-multiple="true" accept="image/*,application/*,.*" ngf-max-size="256MB" ngf-keep="true" ngf-change="change(files)" ngf-pattern="'image/*,.*'">多文件拖拽上傳 </div> <div ngf-no-file-drop>此瀏覽器不支持文件拖拽上傳功能</div> </div> <div class="clear info-space"> <div ng-show="msg.length>0&&isupload" class="col-lg-5 col-lg-offset-3 text-center label-info edit-space">{{msg}} </div> </div> <div class="col-lg-10">文件信息: <ul style="list-style-type:none"> <li ng-repeat="f in files" style="height: 32px" class="col-lg-12"> <div class="col-lg-3" ng-show="f.progress >= 0" style="height: 32px"> <span class="progress"> <div style="width:{{f.progress}}%" ng-bind="f.progress + '%'"> </div> </span> </div> <div class="col-lg-5"> {{f.name.length > 12 ? f.name.substring(0,12)+"...":f.name}} </div> <div class="col-lg-2"> {{f.size/1024>1024?(f.size/(1024*1024)).toFixed(2)+"MB":(f.size/1024).toFixed(2)+"kb"}} </div> <div class="col-lg-2"> <a href ng-click="deleteFile(f.name,files)"> 刪除</a> </div> </li> </ul> </div> <div class="col-lg-2"> <button ng-disabled="files.length>10?true:false" ng-click="uploadFiles(files)" class="btn btn-primary">上傳 </button> </div> </form> </div> </div>
最終效果圖: