Android開發中使用七牛雲存儲進行圖片上傳下載

来源:http://www.cnblogs.com/BobGo/archive/2016/08/03/5734547.html
-Advertisement-
Play Games

Android開發中的圖片存儲本來就是比較耗時耗地的事情,而使用第三方的七牛雲,便可以很好的解決這些後顧之憂,最近我也是在學習七牛的SDK,將使用過程在這記錄下來,方便以後使用。 先說一下七牛雲的存儲原理,上面這幅圖片是官方給出的原理圖,表述當然比較清晰了。可以看出,要進行圖片上傳的話可以分為五大步 ...


  Android開發中的圖片存儲本來就是比較耗時耗地的事情,而使用第三方的七牛雲,便可以很好的解決這些後顧之憂,最近我也是在學習七牛的SDK,將使用過程在這記錄下來,方便以後使用。

        

 

  先說一下七牛雲的存儲原理,上面這幅圖片是官方給出的原理圖,表述當然比較清晰了。可以看出,要進行圖片上傳的話可以分為五大步:

    1. 客戶端用戶登錄到APP的賬號系統裡面;

    2. 客戶端上傳文件之前,需要向業務伺服器申請七牛的上傳憑證,這個憑證由業務伺服器使用七牛提供的服務端SDK生成;

    3. 客戶端使用七牛提供的客戶端SDK,調用上傳方法上傳文件,上傳方法中必須有上傳憑證和文件內容(由於七牛允許大小為0的文件,所以文件上傳之前,建議檢查文件大小。如果業務不允許文件大小為0,那麼需要自行檢測下);

    4. 客戶端文件上傳到七牛之後,可選的操作是七牛回調業務伺服器,(即七牛把文件相關的信息發送POST請求到上傳策略裡面指定的回調地址);

    5. 業務伺服器回覆七牛的回調請求,給出JSON格式的回覆內容(必須是JSON格式的回覆),這個回覆內容將被七牛轉發給客戶端;

  好了,七牛雲的運作原理搞清楚了,仔細理解一下也不是很麻煩嘛,下麵我們來開始整合操作吧。

一、下載官方SDK

  參照七牛雲官網(http://www.qiniu.com/?utm_campaign=baiduSEM&utm_source=baiduSEM&utm_medium=baiduSEM&utm_content=baiduSEM)下載指定SDK,其實根據官方提供的Maven地址下載就好了,在下載最新版QiniuSDK之後,是不是就可以忙著copy開發文檔中的相應代碼了?

  千萬別急,除了依賴qiniu-android-sdk,還要依賴happy-dns,okhttp,android-async-http,這樣一共是四個依賴包。這裡說個小技巧,如果嫌下載那些東西麻煩,可以將官方Demo下載下來,然後將裡邊的依賴包全部放到自己的項目里,當然這樣做的前提是你要分得清哪些是哪些。

二、清單文件添加許可權

  註意:如果使用Android5.0及其以上版本,許可權是要在代碼中申請的。

1 <uses-permission android:name="android.permission.INTERNET"/>
2 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

三、定義變數

  在寫上傳下載代碼前,我們需要先定義以下幾個變數。

 1     private TextView title;  //顯示上傳結果
 2     private ImageView image;  //顯示下載的圖片內容
 3     private ProgressDialog progressDialog;  //上傳進度提示框
 4     private boolean isProgressCancel;  //網路請求過程中是否取消上傳或下載
 5     private UploadManager uploadManager;  //七牛SDK的上傳管理者
 6     private UploadOptions uploadOptions;  //七牛SDK的上傳選項
 7     private MyUpCompletionHandler mHandler;  //七牛SDK的上傳返回監聽
 8     private UpProgressHandler upProgressHandler;  //七牛SDK的上傳進度監聽
 9     private UpCancellationSignal upCancellationSignal;  //七牛SDK的上傳過程取消監聽
10     private final static String TOKEN_URL = "http://xxx.xxx.xxx/x/";  //伺服器請求token的網址
11     private String uptoken;  //伺服器請求Token值
12     private String upKey;  //上傳文件的Key值
13     private byte[] upLoadData;  //上傳的文件

 

四、上傳圖片

  七牛伺服器可以上傳的有三種類型,包括byte[]類型的圖片,String類型的文件路徑,File類型的文件;

(一)從伺服器請求token

 1     private void getTokenFromService() {
 2         //模擬從服務端獲取uptoken
 3         uptoken = "12343232313123";
 4         SyncHttpClient client = new SyncHttpClient();
 5         client.get(TOKEN_URL, new TextHttpResponseHandler() {
 6             @Override
 7             public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
 8                 Log.e("Error", "onFailure: 伺服器請求Token失敗");
 9             }
10 
11             @Override
12             public void onSuccess(int statusCode, Header[] headers, String responseString) {
13                 try {
14                     JSONObject jsonObject = new JSONObject(responseString);
15                     //解析得到的Json串,獲取token值
16                     uptoken = jsonObject.getString("token");
17                 } catch (JSONException e) {
18                     e.printStackTrace();
19                 }
20             }
21         });
22     }

(二)初始化上傳參數

 1     private void initData() {
 2         getTokenFromService();
 3         upKey = getPicture();
 4         uploadManager = new UploadManager();
 5         upProgressHandler = new UpProgressHandler() {
 6             /**
 7              * @param key 上傳時的upKey;
 8              * @param percent 上傳進度;
 9              */
10             @Override
11             public void progress(String key, double percent) {
12                 progressDialog.setProgress((int) (upLoadData.length * percent));
13             }
14         };
15         upCancellationSignal = new UpCancellationSignal() {
16             @Override
17             public boolean isCancelled() {
18                 return isProgressCancel;
19             }
20         };
21         //定義數據或文件上傳時的可選項
22         uploadOptions = new UploadOptions(
23                 null,  //擴展參數,以<code>x:</code>開頭的用戶自定義參數
24                 "mime_type",  //指定上傳文件的MimeType
25                 true,  //是否啟用上傳內容crc32校驗
26                 upProgressHandler,  //上傳內容進度處理
27                 upCancellationSignal  //取消上傳信號
28         );
29         mHandler = new MyUpCompletionHandler();
30     }

(三)啟動非同步線程,上傳圖片文件

 1     public void clickPost(View view) {
 2         if (TextUtils.isEmpty(uptoken)) {
 3             Toast.makeText(MainActivity.this, "正在從網路獲取Token值,請稍後...", Toast.LENGTH_SHORT).show();
 4             return;
 5         }
 6         new Thread(new Runnable() {
 7             @Override
 8             public void run() {
 9                 progressDialog.setMax(upLoadData.length);
10                 progressDialog.show();
11                 uploadManager.put(upLoadData, upKey, uptoken, mHandler, uploadOptions);
12             }
13         }).start();
14     }

五、下載圖片

  該 SDK 並未提供下載文件相關的功能介面,因為文件下載是一個標準的 HTTP GET 過程。開發者只需理解資源 URI 的組成格式即可非常方便的構建資源 URI,併在必要的時候加上下載憑證,即可使用 HTTP GET 請求獲取相應資源。

  上段斜體是從QiniuSDK官網的指導文檔中複製的,所以下載方式比較簡單。

 1     public void clickDown(View view) {
 2         //圖片上傳到七牛之後,
 3         // 預設會將文件的hash和key(文件的文件名)響應回來,
 4         // 然後在空間設置->功能變數名稱設置里,找到空間功能變數名稱,
 5         // 通過http://空間功能變數名稱/key的形式,拿到文件的url。
 6         String fileName = "xxx.xxx.xx/xx";
 7         String downUrl = "http://" + fileName + "/" + upKey;
 8         SyncHttpClient client = new SyncHttpClient();
 9         client.get(downUrl, new BinaryHttpResponseHandler() {
10             @Override
11             public void onSuccess(int statusCode, Header[] headers, byte[] binaryData) {
12                 if (binaryData != null) {
13                     image.setImageBitmap(BitmapFactory.decodeByteArray(binaryData, 0, binaryData.length));
14                 }
15             }
16             @Override
17             public void onFailure(int statusCode, Header[] headers, byte[] binaryData, Throwable error) {
18                 Log.e("Error", "onFailure: 圖片下載失敗" );
19             }
20         });
21     }

六、文檔總結

  有時候看一百遍文字介紹,也不如讀一遍Fuck Code,所以我還是把涉及的文件源碼也copy過來一份,以後也方便看了。

(一)MainActivity.class

  1 package com.example.administrator;
  2 
  3 import android.app.ProgressDialog;
  4 import android.content.DialogInterface;
  5 import android.graphics.BitmapFactory;
  6 import android.os.Bundle;
  7 import android.support.v7.app.AppCompatActivity;
  8 import android.text.TextUtils;
  9 import android.util.Log;
 10 import android.view.View;
 11 import android.widget.ImageView;
 12 import android.widget.TextView;
 13 import android.widget.Toast;
 14 
 15 import com.example.administrator.myqiniudemo.R;
 16 import com.loopj.android.http.BinaryHttpResponseHandler;
 17 import com.loopj.android.http.SyncHttpClient;
 18 import com.loopj.android.http.TextHttpResponseHandler;
 19 import com.qiniu.android.http.ResponseInfo;
 20 import com.qiniu.android.storage.UpCancellationSignal;
 21 import com.qiniu.android.storage.UpCompletionHandler;
 22 import com.qiniu.android.storage.UpProgressHandler;
 23 import com.qiniu.android.storage.UploadManager;
 24 import com.qiniu.android.storage.UploadOptions;
 25 
 26 import org.json.JSONException;
 27 import org.json.JSONObject;
 28 
 29 import cz.msebera.android.httpclient.Header;
 30 
 31 public class MainActivity extends AppCompatActivity {
 32 
 33     private TextView title;  //顯示上傳結果
 34     private ImageView image;  //顯示下載的圖片內容
 35     private ProgressDialog progressDialog;  //上傳進度提示框
 36     private boolean isProgressCancel;  //網路請求過程中是否取消上傳或下載
 37     private UploadManager uploadManager;  //七牛SDK的上傳管理者
 38     private UploadOptions uploadOptions;  //七牛SDK的上傳選項
 39     private MyUpCompletionHandler mHandler;  //七牛SDK的上傳返回監聽
 40     private UpProgressHandler upProgressHandler;  //七牛SDK的上傳進度監聽
 41     private UpCancellationSignal upCancellationSignal;  //七牛SDK的上傳過程取消監聽
 42     private final static String TOKEN_URL = "http://xxx.xxx.xxx/x/";  //伺服器請求token的網址
 43     private String uptoken;  //伺服器請求Token值
 44     private String upKey;  //上傳文件的Key值
 45     private byte[] upLoadData;  //上傳的文件
 46 
 47     @Override
 48     protected void onCreate(Bundle savedInstanceState) {
 49         super.onCreate(savedInstanceState);
 50         setContentView(R.layout.activity_main);
 51         initView();
 52         initData();
 53     }
 54 
 55     private void initData() {
 56         getTokenFromService();
 57         upKey = getPicture();
 58         uploadManager = new UploadManager();
 59         upProgressHandler = new UpProgressHandler() {
 60             /**
 61              * @param key 上傳時的upKey;
 62              * @param percent 上傳進度;
 63              */
 64             @Override
 65             public void progress(String key, double percent) {
 66                 progressDialog.setProgress((int) (upLoadData.length * percent));
 67             }
 68         };
 69         upCancellationSignal = new UpCancellationSignal() {
 70             @Override
 71             public boolean isCancelled() {
 72                 return isProgressCancel;
 73             }
 74         };
 75         //定義數據或文件上傳時的可選項
 76         uploadOptions = new UploadOptions(
 77                 null,  //擴展參數,以<code>x:</code>開頭的用戶自定義參數
 78                 "mime_type",  //指定上傳文件的MimeType
 79                 true,  //是否啟用上傳內容crc32校驗
 80                 upProgressHandler,  //上傳內容進度處理
 81                 upCancellationSignal  //取消上傳信號
 82         );
 83         mHandler = new MyUpCompletionHandler();
 84     }
 85 
 86     private String getPicture() {
 87         //模擬上傳圖片的byte數組,並返迴文件名
 88         upLoadData = new byte[]{1, 2, 3, 1, 2, 3, 12, 3, 4, 2, 1, 2};
 89         return "upload.txt";
 90     }
 91 
 92     private void getTokenFromService() {
 93         //模擬從服務端獲取uptoken
 94         uptoken = "12343232313123";
 95         SyncHttpClient client = new SyncHttpClient();
 96         client.get(TOKEN_URL, new TextHttpResponseHandler() {
 97             @Override
 98             public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
 99                 Log.e("Error", "onFailure: 伺服器請求Token失敗");
100             }
101 
102             @Override
103             public void onSuccess(int statusCode, Header[] headers, String responseString) {
104                 try {
105                     JSONObject jsonObject = new JSONObject(responseString);
106                     //解析得到的Json串,獲取token值
107                     uptoken = jsonObject.getString("token");
108                 } catch (JSONException e) {
109                     e.printStackTrace();
110                 }
111             }
112         });
113     }
114 
115     private void initView() {
116         title = (TextView) findViewById(R.id.title);
117         image = (ImageView) findViewById(R.id.image);
118         initProgressBar();
119     }
120 
121     private void initProgressBar() {
122         progressDialog = new ProgressDialog(MainActivity.this);
123         progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
124         progressDialog.setTitle("進度提示");
125         progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() {
126             @Override
127             public void onClick(DialogInterface dialog, int which) {
128                 isProgressCancel = true;
129             }
130         });
131     }
132 
133     /**
134      * 點擊按鈕,開始文件上傳
135      *
136      * @param view
137      */
138     public void clickPost(View view) {
139         if (TextUtils.isEmpty(uptoken)) {
140             Toast.makeText(MainActivity.this, "正在從網路獲取Token值,請稍後...", Toast.LENGTH_SHORT).show();
141             return;
142         }
143         new Thread(new Runnable() {
144             @Override
145             public void run() {
146                 progressDialog.setMax(upLoadData.length);
147                 progressDialog.show();
148                 uploadManager.put(upLoadData, upKey, uptoken, mHandler, uploadOptions);
149             }
150         });
151     }
152 
153     /**
154      * 點擊按鈕,開始文件下載
155      *
156      * @param view
157      */
158     public void clickDown(View view) {
159         //圖片上傳到七牛之後,
160         // 預設會將文件的hash和key(文件的文件名)響應回來,
161         // 然後在空間設置->功能變數名稱設置里,找到空間功能變數名稱,
162         // 通過http://空間功能變數名稱/key的形式,拿到文件的url。
163         String fileName = "xxx.xxx.xx/xx";
164         String downUrl = "http://" + fileName + "/" + upKey;
165         SyncHttpClient client = new SyncHttpClient();
166         client.get(downUrl, new BinaryHttpResponseHandler() {
167             @Override
168             public void onSuccess(int statusCode, Header[] headers, byte[] binaryData) {
169                 if (binaryData != null) {
170                     image.setImageBitmap(BitmapFactory.decodeByteArray(binaryData, 0, binaryData.length));
171                 }
172             }
173             @Override
174             public void onFailure(int statusCode, Header[] headers, byte[] binaryData, Throwable error) {
175                 Log.e("Error", "onFailure: 圖片下載失敗" );
176             }
177         });
178     }
179 
180     /**
181      * 自定義上傳完成監聽類
182      * 實現QiniuSDK中的UpCompletionHandler介面
183      */
184     public class MyUpCompletionHandler implements UpCompletionHandler {
185         /**
186          * @param key      上傳時的upKey;
187          * @param info     Json串表示的上傳信息,包括使用版本,請求狀態,請求Id等信息;
188          * @param response Json串表示的文件信息,包括文件Hash碼,文件Mime類型,文件大小等信息;
189          */
190         @Override
191         public void complete(String key, ResponseInfo info, JSONObject response) {
192             progressDialog.dismiss();
193             title.setText(key + "!\n" + info + "!\n" + response + "!");
194         }
195     }
196 }
View Code

(二)activity_main.xml

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout
 3     android:orientation="vertical"
 4     xmlns:android="http://schemas.android.com/apk/res/android"
 5     xmlns:tools="http://schemas.android.com/tools"
 6     android:layout_width="match_parent"
 7     android:layout_height="match_parent"
 8     android:gravity="center_horizontal"
 9     tools:context="com.example.administrator.myqiniudemo.MainActivity">
10 
11     <TextView
12         android:id="@+id/title"
13         android:layout_width="wrap_content"
14         android:layout_height="wrap_content"
15         android:text="Hello Qiniu!"/>
16     <Button
17         android:layout_width="wrap_content"
18         android:layout_height="wrap_content"
19         android:text="上傳圖片"
20         android:onClick="clickPost"
21         />
22     <Button
23         android:layout_width="wrap_content"
24         android:layout_height="wrap_content"
25         android:text="下載圖片"
26         android:onClick="clickDown"
27         />
28     <ImageView
29         android:id="@+id/image"
30         android:layout_width="match_parent"
31         android:layout_height="match_parent"/>
32 </LinearLayout>
View Code

 

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • # 介紹1、官方文檔寫法```objcstatic AccountManager *DefaultManager = nil; + (AccountManager *)defaultManager { if (!DefaultManager) DefaultManager = [[self allo... ...
  • Scene Kit 是Apple 向 OS X 開發者們提供的 Cocoa 下的 3D 渲染框架。 Scene Kit 建立在 OpenGL 的基礎上,包含瞭如光照、模型、材質、攝像機等高級引擎特性,這些組件都是面向對象的,你可以用熟悉的 Objective-C 或 Swift 語言來編寫代碼。假如 ...
  • 蘋果手機端應用,如果發佈的到Appstore上,往往比較複雜,周期也比較長,Over-the-Air是Apple在 iOS4 中新加的一項技術,目的是讓開發者能夠脫離Appstore,實現從自己的伺服器下載並安裝iOS應用。簡單地說,就是用戶只需要在Safari中點開一條鏈接,就能直接在主界面中安裝 ...
  • 技術博客原地址:http://www.cnblogs.com/dashunzi/p/ApplePay.html#top 原技術博客中有源碼和視頻,有感興趣的朋友可以研究一下! 一、什麼是Apple Pay? 1. 概念 Apple Pay,簡單來說, 就是一種移動支付方式。通過Touch ID/ P ...
  • 最近做支付寶和微信接入自己APP工程的功能,遇到了一些問題,跟大家分享: 這裡先說Android開發微信支付接入。 首先根據官方文檔進行,對比支付寶的官方文檔,微信部分更顯得“摘要”一些。 導入後自行觸發的Gradle Build無法通過,提示需要Android Build Tool 22,所以又安 ...
  • ...
  • 1. 相關文件夾介紹 在Android項目文件夾裡面,主要的資源文件是放在res文件夾裡面的。assets文件夾是存放不進行編譯加工的原生文件,即該文件夾裡面的文件不會像xml,java文件被預編譯,可以存放一些圖片,html,js, css等文件。在後面會介紹如何讀取assets文件夾的資源! r ...
  • // self.automaticallyAdjustsScrollViewInsets = NO; // // self.edgesForExtendedLayout = UIRectEdgeNone; ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...