阿里云文件存儲OSS的后端與移動端集成

【寫在前面】
建議初次接觸OSS的童鞋可以根據本文自行操作一遍,能先實現功能遭垛,有時間的話再看阿里云OSS的文檔,進行局部優(yōu)化操灿。那是一份什么樣的文檔的呢锯仪?就是你翻來覆去的看,然后你越看就越想把寫文檔的人拉過來揍一頓的感覺趾盐,總之誰看誰知道庶喜。

閱讀本文時,需要注意本文中代碼的注釋內容救鲤;圖片模糊問題不大溃卡,可以查看原圖,而且只要能找準地方就行蜒简,我都打紅框了瘸羡。

【正文】
后端環(huán)境:ubuntu系統(tǒng) + python
移動端: android

本文采用后端授權stsToken給移動端的方式,實現移動端文件直傳OSS搓茬。

【整體流程描述】
移動端向后端發(fā)送獲取stsToken的請求犹赖,后端接收到該請求后,于后端環(huán)境中執(zhí)行請求OSS授權的stsToken的請求卷仑,然后將獲取的stsToken返回給移動端峻村,移動端獲取stsToken后用以實例化OSSCredentialProvider,進而實例化OSS锡凝,通過OSS的實例化對象實現上傳粘昨。

【整體流程圖示】


移動端文件直傳流程圖

【實現過程】

一、在OSS控制臺中:

1、首先創(chuàng)建Bucket空間:
進入OSS控制臺中找到新建Bucket张肾,然后點它芭析。就行了

2、開通sts服務吞瞪,如下圖馁启,進入你的OSS控制臺,點擊紅框中前往RAM控制臺


image.png

如下圖芍秆,點擊開始授權:


image.png

如果你之前沒有創(chuàng)建過RAM賬號惯疙,則此次創(chuàng)建之后會生成AccessKeyId、AccessKeySecret這兩個密鑰和RoleArn這個角色信息妖啥,此次請務必進行保管霉颠。如下圖會先顯示前二者:
image.png

然后會顯示第三個,即角色信息RoleArn荆虱,務必保管好蒿偎,如下圖:


image.png

上圖中點擊開始授權之后便會生成一個RAM子賬號,生成該賬號之后進入用戶管理頁面克伊,如下圖酥郭,紅框中即為新建的RAM賬戶:


image.png

點擊上圖紅框中右側的授權华坦,彈出授權框:
我看右側紅框中的那個權限可以管理整個對象存儲服務愿吹,所以就加了進來,點擊確定即可:


image.png

至此惜姐,RAM子賬號就創(chuàng)建完畢了犁跪。

二、后端服務器:

1歹袁、安裝pythonSDK:
在安裝SDK之前需要先安裝python-devel庫坷衍,至于原因,可以去原文檔中查找条舔,本文只講述實現過程枫耳。
在Ubuntu與Debian系統(tǒng)中安裝方式:

apt-get install python-dev

若因權限導致無法安裝,那就加sudo

開始安裝SKD:
通過pip方式安裝

pip install oss2

驗證安裝版本:
進入python的交互模式進行如下操作孟抗,

>>> import oss2
>>> oss2.__version__

如果安裝無誤則應該返回版本號迁杨,應該是大于2版本的。
如果整個安裝過程有任何問題凄硼,請看原文檔的解決方案铅协,一般不會有問題。

原文檔地址:
https://help.aliyun.com/document_detail/85288.html?spm=a2c4g.11186623.6.705.75404947Sj1KeS

2摊沉、向sts服務器請求stsToken:
首先需要有sts這個庫狐史,只要一步安裝操作:

pip install aliyun-python-sdk-sts

下面就是在python中請求stsToken:

def getToken():

    # Endpoint以杭州為例,其它Region請按實際情況填寫。
    endpoint = 'oss-cn-hangzhou.aliyuncs.com'
    # 阿里云主賬號AccessKey擁有所有API的訪問權限骏全,風險很高苍柏。強烈建議您創(chuàng)建并使用RAM賬號進行API訪問或日常運維,請登錄 https://ram.console.aliyun.com 創(chuàng)建RAM賬號吟温。
    access_key_id = 'LTAIq*******'                   #替換成你的
    access_key_secret = 'wVlXxgdW*******'            #替換成你的
    bucket_name = '你的存儲空間名稱'                  #替換成你的
    # role_arn是角色的資源名稱序仙。
    role_arn = 'acs:ram::16484498*******eratorrole'  #替換成你的

    clt = client.AcsClient(access_key_id, access_key_secret, 'cn-hangzhou')
    req = AssumeRoleRequest.AssumeRoleRequest()

    # 設置返回值格式為JSON。
    req.set_accept_format('json')
    req.set_RoleArn(role_arn)
    req.set_RoleSessionName('session-name')
    body = clt.do_action(req)

    # 使用RAM賬號的AccessKeyId和AccessKeySecret向STS申請臨時token鲁豪,這個token將會傳給移動端使用潘悼。
    stsToken = json.loads(body.decode())

    return stsToken

我返回給前端這個stsToken數據結構如下圖所示:


stsToken數據結構圖

移動端就是要紅框中的四個字段,這四個字段必須要返回給移動端保存爬橡,也不必管這個四個字段是干什么的治唤。
至此,后端請求stsToken并將其返回給移動端的授權過程結束糙申。

三宾添、移動端(本文中為Android):
1、首先在gradle的dependencies中添加oss的依賴:

// 阿里云oss
implementation 'com.aliyun.dpa:oss-android-sdk:+'

原文檔中說在Maven項目中加入依賴柜裸,當時感覺明顯是在gradle缕陕,難道是我孤陋寡聞了?就問了一下阿里那邊疙挺,最后表示就是gradle扛邑。

2、添加權限:
注意安卓6.0以后需要使用動態(tài)權限铐然,自行處理吧

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

3蔬崩、添加混淆:
在proguard-rules.pro文件中添加:

-keep class com.alibaba.sdk.android.oss.** { *; }
-dontwarn okio.**
-dontwarn org.apache.commons.codec.binary.**

然后注意設置:

 release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }

4、然后就是在代碼中使用:

//請求后端返回StsToken
private void getSts(){
    basicsNetWorkAPI = HttpClient.create(BasicsNetWorkAPI.class);
    //請求后端返回stsToken的接口搀暑,每個人的網絡請求也許不一樣沥阳,因此,獲取的stsToken結果自点,請各自保存
    Call<StsServerBean> call = basicsNetWorkAPI.getStsToken();
    call.enqueue(new Callback<StsServerBean>() {
        @Override
        public void onResponse(retrofit2.Call<StsServerBean> call, Response<StsServerBean> response) {
            //上文中stsToken數據結構圖中的紅框中的四個字段內容被我封裝成一個Bean桐罕,為方便理解取名為stsTokenBean
            //為簡化理解,后文中所述stsToken為由該四個字段所組成桂敛,而不是前文的stsToken數據結構圖的那一大坨json功炮,因為其他字段用不到
            StsTokenBean stsTokenBean = response.body().getCredentials();

            //請求成功后,獲取到那四個字段并保存到StsTokenBean后埠啃,應該調用上傳文件的方法向OSS進行上傳死宣。
            //事實上,此處的StsTokenBean應該保存到緩存碴开,因為移動端并不是每次上傳文件到OSS都需要請求stsToken的
            //因為那樣就會很麻煩毅该,因次博秫,請求一次之后就會存在一個有效期,在有效期內可以直接再次對OSS進行操作眶掌,而上述四個參數中的Expiration即用來描述有效期的
            //你可以自行設置挡育,在超過有效期后進行重新獲取stsToken的操作,當然若時間緊迫朴爬,你也可以按照本文的方式首先實現功能即可即寒。后續(xù)改進

            //上傳文件
            upload_file(stsTokenBean);
        }

        @Override
        public void onFailure(retrofit2.Call<StsServerBean> call, Throwable t) {

        }
    });
}

//上傳文件方法
private void upload_file(StsTokenBean stsTokenBean){
    //根據你的OSS的地區(qū)而自行定義,本文中的是杭州
    String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";

    //移動端建議使用該方式召噩,此時母赵,stsToken中的前三個參數就派上用場了
    OSSCredentialProvider credentialProvider = new OSSStsTokenCredentialProvider(stsTokenBean.getAccessKeyId(), stsTokenBean.getAccessKeySecret(), stsTokenBean.getSecurityToken());

    // 配置類如果不設置,會有默認配置具滴。
    ClientConfiguration conf = new ClientConfiguration();
    conf.setConnectionTimeout(15 * 1000);   // 連接超時凹嘲,默認15秒。
    conf.setSocketTimeout(15 * 1000);       // socket超時构韵,默認15秒周蹭。
    conf.setMaxConcurrentRequest(5);        // 最大并發(fā)請求數,默認5個疲恢。
    conf.setMaxErrorRetry(2);               // 失敗后最大重試次數凶朗,默認2次。

    //初始化OSS服務的客戶端oss
    //事實上显拳,初始化OSS的實例對象棚愤,應該具有與整個應用程序相同的生命周期,在應用程序生命周期結束時銷毀
    //但這里只是實現功能萎攒,若時間緊遇八,你仍然可以按照本文方式先將功能實現矛绘,然后優(yōu)化
    OSS oss = new OSSClient(getActivity().getApplicationContext(), endpoint, credentialProvider, conf);

    //當前時間戳耍休,用于自定義文件在OSS中存儲路徑末尾的名稱
    image_url_time = System.currentTimeMillis() + "";

    // 構造上傳請求,第二個數參是ObjectName,第三個參數是本地文件路徑
    PutObjectRequest put = new PutObjectRequest("first-images", image_url_time, loacalFilePath);

    //異步上傳可以設置進度回調
    put.setProgressCallback(new OSSProgressCallback<PutObjectRequest>() {
        @Override
        public void onProgress(PutObjectRequest request, long currentSize, long totalSize) {

            Log.i("上傳進度:", "當前進度" + currentSize + "   總進度" + totalSize);

        }
    });

    //實現異步上傳
    OSSAsyncTask task = oss.asyncPutObject(put, new OSSCompletedCallback<PutObjectRequest, PutObjectResult>() {
        @Override
        public void onSuccess(PutObjectRequest request, PutObjectResult result) {
            Log.d("PutObject", "UploadSuccess");
            Log.d("ETag", result.getETag());
            Log.d("RequestId", result.getRequestId());

            //這個image_url左邊的字符串部分是我OSS的Bucket的文件存儲地址货矮,根據個人的文件存儲地址不同羊精,替換成自己的即可,而后面的image_url_time則是為了區(qū)分每個文件的文件名
            //注意囚玫,最好的方式是設置回調喧锦,因為回調的功能必須要在線上服務器才能測試,我服務器在本地環(huán)境中是不允許回調的
            //在咨詢阿里云相關人員之后抓督,他們說也允許記住地址燃少,進行拼接的方式保存線上文件url路徑
            //但是這種方式需要在OSS的管理控制臺中將你的存儲空間設置為公共讀的方式,不然沒法用下面的拼接鏈接铃在。
            //此時你上傳的文件所在的線上地址就已經獲得了阵具,想怎么使用則隨意了
            image_url = "http://first********ngzhou.aliyuncs.com/" + image_url_time;
        }

        @Override
        public void onFailure(PutObjectRequest request, ClientException clientException, ServiceException serviceException) {
            if (clientException != null) {
                // 本地異常碍遍,如網絡異常等。
                clientException.printStackTrace();
            }
            if (serviceException != null) {
                // 服務異常阳液。
                Log.e("ErrorCode", serviceException.getErrorCode());
                Log.e("RequestId", serviceException.getRequestId());
                Log.e("HostId", serviceException.getHostId());
                Log.e("RawMessage", serviceException.getRawMessage());
            }
        }
    });
    // 等異步上傳過程完成
    task.waitUntilFinished();
    Toast.makeText(getActivity(), "上傳成功", Toast.LENGTH_SHORT).show();

至此怕敬,移動端的直接上傳文件到OSS的過程也結束了。你可以去自己的OSS控制臺看看是否新增了剛才上傳的文件帘皿。

整個OSS的集成過程完成东跪!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市鹰溜,隨后出現的幾起案子虽填,更是在濱河造成了極大的恐慌,老刑警劉巖曹动,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件卤唉,死亡現場離奇詭異,居然都是意外死亡仁期,警方通過查閱死者的電腦和手機桑驱,發(fā)現死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來跛蛋,“玉大人熬的,你說我怎么就攤上這事∩藜叮” “怎么了押框?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長理逊。 經常有香客問我橡伞,道長,這世上最難降的妖魔是什么晋被? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任兑徘,我火速辦了婚禮,結果婚禮上羡洛,老公的妹妹穿的比我還像新娘挂脑。我一直安慰自己,他們只是感情好欲侮,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布崭闲。 她就那樣靜靜地躺著,像睡著了一般威蕉。 火紅的嫁衣襯著肌膚如雪刁俭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天韧涨,我揣著相機與錄音牍戚,去河邊找鬼沙兰。 笑死,一個胖子當著我的面吹牛翘魄,可吹牛的內容都是我干的鼎天。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼暑竟,長吁一口氣:“原來是場噩夢啊……” “哼斋射!你這毒婦竟也來了?” 一聲冷哼從身側響起但荤,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤罗岖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后腹躁,有當地人在樹林里發(fā)現了一具尸體桑包,經...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年纺非,在試婚紗的時候發(fā)現自己被綠了哑了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡烧颖,死狀恐怖弱左,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情炕淮,我是刑警寧澤拆火,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站涂圆,受9級特大地震影響们镜,放射性物質發(fā)生泄漏。R本人自食惡果不足惜润歉,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一模狭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧卡辰,春花似錦胞皱、人聲如沸邪意。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽雾鬼。三九已至萌朱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間策菜,已是汗流浹背晶疼。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工酒贬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人翠霍。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓锭吨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親寒匙。 傳聞我的和親對象是個殘疾皇子零如,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內容