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

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

        

 

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

    1. 客戶端用戶登陸到APP的帳號系統裏面;json

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

    3. 客戶端使用七牛提供的客戶端SDK,調用上傳方法上傳文件,上傳方法中必須有上傳憑證和文件內容(因爲七牛容許大小爲0的文件,因此文件上傳以前,建議檢查文件大小。若是業務不容許文件大小爲0,那麼須要自行檢測下);服務器

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

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

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

1、下載官方SDKasync

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

  千萬別急,除了依賴qiniu-android-sdk,還要依賴happy-dns,okhttp,android-async-http,這樣一共是四個依賴包。這裏說個小技巧,若是嫌下載那些東西麻煩,能夠將官方Demo下載下來,而後將裏邊的依賴包所有放到本身的項目裏,固然這樣作的前提是你要分得清哪些是哪些。

2、清單文件添加權限

  注意:若是使用Android5.0及其以上版本,權限是要在代碼中申請的。

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

3、定義變量

  在寫上傳下載代碼前,咱們須要先定義如下幾個變量。

 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;  //上傳的文件

 

4、上傳圖片

  七牛服務器能夠上傳的有三種類型,包括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     }

5、下載圖片

  該 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     }

6、文檔總結

  有時候看一百遍文字介紹,也不如讀一遍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
相關文章
相關標籤/搜索