Android中使用七牛云存儲(chǔ)進(jìn)行圖片上傳下載的實(shí)例代碼
Android開(kāi)發(fā)中的圖片存儲(chǔ)本來(lái)就是比較耗時(shí)耗地的事情,而使用第三方的七牛云,便可以很好的解決這些后顧之憂,最近我也是在學(xué)習(xí)七牛的SDK,將使用過(guò)程在這記錄下來(lái),方便以后使用。
先說(shuō)一下七牛云的存儲(chǔ)原理,上面這幅圖片是官方給出的原理圖,表述當(dāng)然比較清晰了。
可以看出,要進(jìn)行圖片上傳的話可以分為五大步:
1. 客戶端用戶登錄到APP的賬號(hào)系統(tǒng)里面;
2. 客戶端上傳文件之前,需要向業(yè)務(wù)服務(wù)器申請(qǐng)七牛的上傳憑證,這個(gè)憑證由業(yè)務(wù)服務(wù)器使用七牛提供的服務(wù)端SDK生成;
3. 客戶端使用七牛提供的客戶端SDK,調(diào)用上傳方法上傳文件,上傳方法中必須有上傳憑證和文件內(nèi)容(由于七牛允許大小為0的文件,所以文件上傳之前,建議檢查文件大小。如果業(yè)務(wù)不允許文件大小為0,那么需要自行檢測(cè)下);
4. 客戶端文件上傳到七牛之后,可選的操作是七?;卣{(diào)業(yè)務(wù)服務(wù)器,(即七牛把文件相關(guān)的信息發(fā)送POST請(qǐng)求到上傳策略里面指定的回調(diào)地址);
5. 業(yè)務(wù)服務(wù)器回復(fù)七牛的回調(diào)請(qǐng)求,給出JSON格式的回復(fù)內(nèi)容(必須是JSON格式的回復(fù)),這個(gè)回復(fù)內(nèi)容將被七牛轉(zhuǎn)發(fā)給客戶端;
好了,七牛云的運(yùn)作原理搞清楚了,仔細(xì)理解一下也不是很麻煩嘛,下面我們來(lái)開(kāi)始整合操作吧。
一、下載官方SDK
參照七牛云官網(wǎng)(http://www.qiniu.com/?utm_campaign=baiduSEM&utm_source=baiduSEM&utm_medium=baiduSEM&utm_content=baiduSEM)下載指定SDK,其實(shí)根據(jù)官方提供的Maven地址下載就好了,在下載最新版QiniuSDK之后,是不是就可以忙著copy開(kāi)發(fā)文檔中的相應(yīng)代碼了?
千萬(wàn)別急,除了依賴qiniu-android-sdk,還要依賴happy-dns,okhttp,android-async-http,這樣一共是四個(gè)依賴包。這里說(shuō)個(gè)小技巧,如果嫌下載那些東西麻煩,可以將官方Demo下載下來(lái),然后將里邊的依賴包全部放到自己的項(xiàng)目里,當(dāng)然這樣做的前提是你要分得清哪些是哪些。
二、清單文件添加權(quán)限
注意:如果使用Android5.0及其以上版本,權(quán)限是要在代碼中申請(qǐng)的。
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
三、定義變量
在寫(xiě)上傳下載代碼前,我們需要先定義以下幾個(gè)變量。
private TextView title; //顯示上傳結(jié)果 private ImageView image; //顯示下載的圖片內(nèi)容 private ProgressDialog progressDialog; //上傳進(jìn)度提示框 private boolean isProgressCancel; //網(wǎng)絡(luò)請(qǐng)求過(guò)程中是否取消上傳或下載 private UploadManager uploadManager; //七牛SDK的上傳管理者 private UploadOptions uploadOptions; //七牛SDK的上傳選項(xiàng) private MyUpCompletionHandler mHandler; //七牛SDK的上傳返回監(jiān)聽(tīng) private UpProgressHandler upProgressHandler; //七牛SDK的上傳進(jìn)度監(jiān)聽(tīng) private UpCancellationSignal upCancellationSignal; //七牛SDK的上傳過(guò)程取消監(jiān)聽(tīng) private final static String TOKEN_URL = "http://xxx.xxx.xxx/x/"; //服務(wù)器請(qǐng)求token的網(wǎng)址 private String uptoken; //服務(wù)器請(qǐng)求Token值 private String upKey; //上傳文件的Key值 private byte[] upLoadData; //上傳的文件
四、上傳圖片
七牛服務(wù)器可以上傳的有三種類型,包括byte[]類型的圖片,String類型的文件路徑,F(xiàn)ile類型的文件;
(一)從服務(wù)器請(qǐng)求token
private void getTokenFromService() { //模擬從服務(wù)端獲取uptoken uptoken = "12343232313123"; SyncHttpClient client = new SyncHttpClient(); client.get(TOKEN_URL, new TextHttpResponseHandler() { @Override public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) { Log.e("Error", "onFailure: 服務(wù)器請(qǐng)求Token失敗"); } @Override public void onSuccess(int statusCode, Header[] headers, String responseString) { try { JSONObject jsonObject = new JSONObject(responseString); //解析得到的Json串,獲取token值 uptoken = jsonObject.getString("token"); } catch (JSONException e) { e.printStackTrace(); } } }); }
(二)初始化上傳參數(shù)
private void initData() { getTokenFromService(); upKey = getPicture(); uploadManager = new UploadManager(); upProgressHandler = new UpProgressHandler() { /** * @param key 上傳時(shí)的upKey; * @param percent 上傳進(jìn)度; */ @Override public void progress(String key, double percent) { progressDialog.setProgress((int) (upLoadData.length * percent)); } }; upCancellationSignal = new UpCancellationSignal() { @Override public boolean isCancelled() { return isProgressCancel; } }; //定義數(shù)據(jù)或文件上傳時(shí)的可選項(xiàng) uploadOptions = new UploadOptions( null, //擴(kuò)展參數(shù),以<code>x:</code>開(kāi)頭的用戶自定義參數(shù) "mime_type", //指定上傳文件的MimeType true, //是否啟用上傳內(nèi)容crc32校驗(yàn) upProgressHandler, //上傳內(nèi)容進(jìn)度處理 upCancellationSignal //取消上傳信號(hào) ); mHandler = new MyUpCompletionHandler(); }
(三)啟動(dòng)異步線程,上傳圖片文件
public void clickPost(View view) { if (TextUtils.isEmpty(uptoken)) { Toast.makeText(MainActivity.this, "正在從網(wǎng)絡(luò)獲取Token值,請(qǐng)稍后...", Toast.LENGTH_SHORT).show(); return; } new Thread(new Runnable() { @Override public void run() { progressDialog.setMax(upLoadData.length); progressDialog.show(); uploadManager.put(upLoadData, upKey, uptoken, mHandler, uploadOptions); } }); }
五、下載圖片
該 SDK 并未提供下載文件相關(guān)的功能接口,因?yàn)槲募螺d是一個(gè)標(biāo)準(zhǔn)的 HTTP GET 過(guò)程。開(kāi)發(fā)者只需理解資源 URI 的組成格式即可非常方便的構(gòu)建資源 URI,并在必要的時(shí)候加上下載憑證,即可使用 HTTP GET 請(qǐng)求獲取相應(yīng)資源。
上段斜體是從QiniuSDK官網(wǎng)的指導(dǎo)文檔中復(fù)制的,所以下載方式比較簡(jiǎn)單。
public void clickDown(View view) { //圖片上傳到七牛之后, // 默認(rèn)會(huì)將文件的hash和key(文件的文件名)響應(yīng)回來(lái), // 然后在空間設(shè)置->域名設(shè)置里,找到空間域名, // 通過(guò)http://空間域名/key的形式,拿到文件的url。 String fileName = "xxx.xxx.xx/xx"; String downUrl = "http://" + fileName + "/" + upKey; SyncHttpClient client = new SyncHttpClient(); client.get(downUrl, new BinaryHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, byte[] binaryData) { if (binaryData != null) { image.setImageBitmap(BitmapFactory.decodeByteArray(binaryData, 0, binaryData.length)); } } @Override public void onFailure(int statusCode, Header[] headers, byte[] binaryData, Throwable error) { Log.e("Error", "onFailure: 圖片下載失敗" ); } }); }
六、文檔總結(jié)
有時(shí)候看一百遍文字介紹,也不如讀一遍Fuck Code,所以我還是把涉及的文件源碼也copy過(guò)來(lái)一份,以后也方便看了。
(一)MainActivity.class
package com.example.administrator; import android.app.ProgressDialog; import android.content.DialogInterface; import android.graphics.BitmapFactory; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import com.example.administrator.myqiniudemo.R; import com.loopj.android.http.BinaryHttpResponseHandler; import com.loopj.android.http.SyncHttpClient; import com.loopj.android.http.TextHttpResponseHandler; import com.qiniu.android.http.ResponseInfo; import com.qiniu.android.storage.UpCancellationSignal; import com.qiniu.android.storage.UpCompletionHandler; import com.qiniu.android.storage.UpProgressHandler; import com.qiniu.android.storage.UploadManager; import com.qiniu.android.storage.UploadOptions; import org.json.JSONException; import org.json.JSONObject; import cz.msebera.android.httpclient.Header; public class MainActivity extends AppCompatActivity { private TextView title; //顯示上傳結(jié)果 private ImageView image; //顯示下載的圖片內(nèi)容 private ProgressDialog progressDialog; //上傳進(jìn)度提示框 private boolean isProgressCancel; //網(wǎng)絡(luò)請(qǐng)求過(guò)程中是否取消上傳或下載 private UploadManager uploadManager; //七牛SDK的上傳管理者 private UploadOptions uploadOptions; //七牛SDK的上傳選項(xiàng) private MyUpCompletionHandler mHandler; //七牛SDK的上傳返回監(jiān)聽(tīng) private UpProgressHandler upProgressHandler; //七牛SDK的上傳進(jìn)度監(jiān)聽(tīng) private UpCancellationSignal upCancellationSignal; //七牛SDK的上傳過(guò)程取消監(jiān)聽(tīng) private final static String TOKEN_URL = "http://xxx.xxx.xxx/x/"; //服務(wù)器請(qǐng)求token的網(wǎng)址 private String uptoken; //服務(wù)器請(qǐng)求Token值 private String upKey; //上傳文件的Key值 private byte[] upLoadData; //上傳的文件 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initData(); } private void initData() { getTokenFromService(); upKey = getPicture(); uploadManager = new UploadManager(); upProgressHandler = new UpProgressHandler() { /** * @param key 上傳時(shí)的upKey; * @param percent 上傳進(jìn)度; */ @Override public void progress(String key, double percent) { progressDialog.setProgress((int) (upLoadData.length * percent)); } }; upCancellationSignal = new UpCancellationSignal() { @Override public boolean isCancelled() { return isProgressCancel; } }; //定義數(shù)據(jù)或文件上傳時(shí)的可選項(xiàng) uploadOptions = new UploadOptions( null, //擴(kuò)展參數(shù),以<code>x:</code>開(kāi)頭的用戶自定義參數(shù) "mime_type", //指定上傳文件的MimeType true, //是否啟用上傳內(nèi)容crc32校驗(yàn) upProgressHandler, //上傳內(nèi)容進(jìn)度處理 upCancellationSignal //取消上傳信號(hào) ); mHandler = new MyUpCompletionHandler(); } private String getPicture() { //模擬上傳圖片的byte數(shù)組,并返回文件名 upLoadData = new byte[]{1, 2, 3, 1, 2, 3, 12, 3, 4, 2, 1, 2}; return "upload.txt"; } private void getTokenFromService() { //模擬從服務(wù)端獲取uptoken uptoken = "12343232313123"; SyncHttpClient client = new SyncHttpClient(); client.get(TOKEN_URL, new TextHttpResponseHandler() { @Override public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) { Log.e("Error", "onFailure: 服務(wù)器請(qǐng)求Token失敗"); } @Override public void onSuccess(int statusCode, Header[] headers, String responseString) { try { JSONObject jsonObject = new JSONObject(responseString); //解析得到的Json串,獲取token值 uptoken = jsonObject.getString("token"); } catch (JSONException e) { e.printStackTrace(); } } }); } private void initView() { title = (TextView) findViewById(R.id.title); image = (ImageView) findViewById(R.id.image); initProgressBar(); } private void initProgressBar() { progressDialog = new ProgressDialog(MainActivity.this); progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.setTitle("進(jìn)度提示"); progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { isProgressCancel = true; } }); } /** * 點(diǎn)擊按鈕,開(kāi)始文件上傳 * * @param view */ public void clickPost(View view) { if (TextUtils.isEmpty(uptoken)) { Toast.makeText(MainActivity.this, "正在從網(wǎng)絡(luò)獲取Token值,請(qǐng)稍后...", Toast.LENGTH_SHORT).show(); return; } new Thread(new Runnable() { @Override public void run() { progressDialog.setMax(upLoadData.length); progressDialog.show(); uploadManager.put(upLoadData, upKey, uptoken, mHandler, uploadOptions); } }); } /** * 點(diǎn)擊按鈕,開(kāi)始文件下載 * * @param view */ public void clickDown(View view) { //圖片上傳到七牛之后, // 默認(rèn)會(huì)將文件的hash和key(文件的文件名)響應(yīng)回來(lái), // 然后在空間設(shè)置->域名設(shè)置里,找到空間域名, // 通過(guò)http://空間域名/key的形式,拿到文件的url。 String fileName = "xxx.xxx.xx/xx"; String downUrl = "http://" + fileName + "/" + upKey; SyncHttpClient client = new SyncHttpClient(); client.get(downUrl, new BinaryHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, byte[] binaryData) { if (binaryData != null) { image.setImageBitmap(BitmapFactory.decodeByteArray(binaryData, 0, binaryData.length)); } } @Override public void onFailure(int statusCode, Header[] headers, byte[] binaryData, Throwable error) { Log.e("Error", "onFailure: 圖片下載失敗" ); } }); } /** * 自定義上傳完成監(jiān)聽(tīng)類 * 實(shí)現(xiàn)QiniuSDK中的UpCompletionHandler接口 */ public class MyUpCompletionHandler implements UpCompletionHandler { /** * @param key 上傳時(shí)的upKey; * @param info Json串表示的上傳信息,包括使用版本,請(qǐng)求狀態(tài),請(qǐng)求Id等信息; * @param response Json串表示的文件信息,包括文件Hash碼,文件Mime類型,文件大小等信息; */ @Override public void complete(String key, ResponseInfo info, JSONObject response) { progressDialog.dismiss(); title.setText(key + "!\n" + info + "!\n" + response + "!"); } } }
(二)activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" tools:context="com.example.administrator.myqiniudemo.MainActivity"> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello Qiniu!"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="上傳圖片" android:onClick="clickPost" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="下載圖片" android:onClick="clickDown" /> <ImageView android:id="@+id/image" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>
以上所述是小編給大家介紹的Android中使用七牛云存儲(chǔ)進(jìn)行圖片上傳下載的實(shí)例代碼,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
Android項(xiàng)目實(shí)現(xiàn)短信的發(fā)送、接收和對(duì)短信進(jìn)行攔截
本篇文章主要介紹了Android項(xiàng)目實(shí)現(xiàn)短信的發(fā)送、接收和對(duì)短信進(jìn)行攔截,這是學(xué)習(xí)Android比較入門的東西,有需要的可以了解一下。2016-10-10Android App中使用RatingBar實(shí)現(xiàn)星級(jí)打分功能的教程
這篇文章主要介紹了Android App中使用RatingBar實(shí)現(xiàn)星級(jí)打分功能的教程,文中舉了一個(gè)使用SeekBar與RatingBar制作的應(yīng)用內(nèi)打分條的功能,非常簡(jiǎn)單,需要的朋友可以參考下2016-04-04Android拖動(dòng)條的實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了Android拖動(dòng)條的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09Android中數(shù)據(jù)庫(kù)常見(jiàn)操作實(shí)例分析
這篇文章主要介紹了Android中數(shù)據(jù)庫(kù)常見(jiàn)操作,以完整實(shí)例形式較為詳細(xì)的分析了Android基于數(shù)據(jù)庫(kù)類進(jìn)行數(shù)據(jù)庫(kù)的增刪改查等操作技巧,需要的朋友可以參考下2015-10-10TabLayout實(shí)現(xiàn)ViewPager指示器的方法
這篇文章主要為大家詳細(xì)介紹了TabLayout實(shí)現(xiàn)ViewPager指示器,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06詳解如何在Android studio中更新sdk版本和build-tools版本
這篇文章主要介紹了如何在Android studio中更新sdk版本和build-tools版本,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11android webview 中l(wèi)ocalStorage無(wú)效的解決方法
這篇文章主要介紹了android webview 中l(wèi)ocalStorage無(wú)效的解決方法,本文直接給出解決方法實(shí)現(xiàn)代碼,需要的朋友可以參考下2015-06-06Android編程實(shí)現(xiàn)獲取系統(tǒng)內(nèi)存、CPU使用率及狀態(tài)欄高度的方法示例
這篇文章主要介紹了Android編程實(shí)現(xiàn)獲取系統(tǒng)內(nèi)存、CPU使用率及狀態(tài)欄高度的方法,涉及Android基于自定義類實(shí)現(xiàn)針對(duì)系統(tǒng)硬件信息的相關(guān)獲取操作技巧,需要的朋友可以參考下2017-08-08