angulaijs中的ng-upload-file與阿里雲oss服務的結合,實現在瀏覽器端上傳文件到阿里雲(速度可以達到1.5M)


  1. 2015-10-26
  2. angularjs結合aliyun瀏覽器端oos文件上傳加臨時身份驗證例子
    1. 在服務端獲取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例子如下:

 

  1. 前端js獲取sts且添加工具包oss-js-upload.js和aliyun-sdk-js.js,詳情請參考以下網址https://github.com/aliyun-UED/oss-js-uploadhttps://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">

                            &nbsp;&nbsp;{{f.name.length > 12 ? f.name.substring(0,12)+"...":f.name}}

                            </div>

                        <div class="col-lg-2">

                            &nbsp;&nbsp;{{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>

 

 

最終效果圖:

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM