国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

OkHttp基本使用(三)上傳下載功能實現

2019-11-06 09:44:53
字體:
來源:轉載
供稿:網友
前言本篇將使用OkHttp實現文件的上傳和下載,以及下載實現斷點續傳功能。因為是基本的使用,此系列文章主要是以大家會用為主而寫的。當然,只要會用了,后面的優化、封裝等等就不難了。下載使用OkHttp完成下載功能,實現斷點續傳,并附帶進度條顯示下載進度。文件下載的交互過程: 下載的流程: 文件下載的代碼:public class DownloadActivity extends AppCompatActivity {    PRivate ProgressBar mProgressBar;    //準備下載    public static final int BEGIN = 0;    //正在下載    public static final int DOWNLOADING = 1;    //結束下載    public static final int END = 2;    //下載的進度    private static int progress;    //是否停止下載    private boolean cancel ;    OkHttpClient okHttpClient = new OkHttpClient();    MyHandler mHandler = new MyHandler(this);    private ImageView mShowImage;    ByteArrayOutputStream baos = new ByteArrayOutputStream();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_download);        mProgressBar = (ProgressBar) findViewById(R.id.down_progress_bar);        mShowImage = (ImageView) findViewById(R.id.down_image);    }    public void click2(View view) {        cancel = true;    }    public void click(View view) {        cancel = false;        new Thread(new Runnable() {            @Override            public void run() {                //實例化Builder對象                Request.Builder builder = new Request.Builder();                //設置Url                builder.url(Config.IMAGE_URL);                //獲取已經下載的大小                int size = baos.size();                //size表示已經下載的大小。如果不為0,則進行斷點續傳。                if (size > 0) {                    //設置斷點續傳的開始位置,格式bytes=123456-                    builder.header("Range", "bytes=" + size + "-");                    //設置ProgressBar的當前進度從停止位置開始                    progress = size;                }                //創建Request對象                Request request = builder.build();                try {                    //執行下載請求,并獲得Response對象                    Response response = okHttpClient.newCall(request).execute();                    //請求成功                    if (response.isSuccessful()) {                        //從Response對象中獲取輸入流對象                        InputStream inputStream = response.body().byteStream();                        //size==0表示第一次下載,非斷點續傳                        if (size == 0) {                            //獲取文件的大小                            int contentLength = (int) response.body().contentLength();                            //將文件總大小通過Handler傳遞到UI線程,設置ProgressBar的總進度值                            mHandler.obtainMessage(BEGIN,contentLength,0).sendToTarget();                        }                        int len = 0;                        byte[] buffer = new byte[1024];                        //循環讀取文件流,開始下載                        while((len = inputStream.read(buffer)) != -1) {                            if (cancel) {                                //如果點擊了停止按鈕,cancel為true。則結束循環                                break;                            }                            //將流寫入緩存                            baos.write(buffer,0,len);                            baos.flush();                            //發送下載進度                            mHandler.obtainMessage(DOWNLOADING,len,0).sendToTarget();                        }                        //下載完成,結束請求,關閉body                        response.body().close();                        //將字節轉成Bitmap對象                        byte[] bytes = baos.toByteArray();                        Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);                        //下載完成通知更新試圖                        mHandler.obtainMessage(END,bitmap).sendToTarget();                    }                } catch (IOException e) {                    e.printStackTrace();                }            }        }).start();    }    static class MyHandler extends Handler {        private WeakReference<DownloadActivity> activityWeakReference;        public MyHandler(DownloadActivity activity) {            this.activityWeakReference = new WeakReference<DownloadActivity>(activity);        }        @Override        public void handleMessage(Message msg) {            switch (msg.what) {                case BEGIN:                    activityWeakReference.get().mProgressBar.setMax(msg.arg1);                    break;                case DOWNLOADING:                    progress += msg.arg1;                    activityWeakReference.get().mProgressBar.setProgress(progress);                    break;                case END:                    progress = 0;                    activityWeakReference.get().mShowImage.setImageBitmap((Bitmap)msg.obj);                    break;            }        }    }}復制代碼以上是文件下的代碼。實現了斷點續傳,其中能進行斷點續傳的關鍵代碼為builder.header("Range", "bytes=" + size + "-");代碼中都有注釋,結合上面的流程圖應該不難理解。代碼解釋:源碼的效果是點擊開始按鈕出發click事件開始下載,點擊停止按鈕觸發click2事件中斷下載。下載的進度監聽是在while循環中,通過Handler進行的進度更新。文件上傳本案例中,實現帶參數的文件上傳功能-----同時完成參數傳遞和文件上傳。代碼如下:public class UploadActivity extends AppCompatActivity {    public static final int GET_PIC = 1;    private ImageView mShowImage;    private Uri uri;    OkHttpClient okHttpClient = new OkHttpClient();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_upload);        mShowImage = (ImageView) findViewById(R.id.upload_show_image);    }    public void click(View view) {        switch (view.getId()) {            case R.id.upload_choose_file:                choosePic();//選擇圖片                break;            case R.id.upload_start:                upload();//上傳                break;        }    }    /**     * 上傳     */    private void upload() {        if (uri == null) {            Toast.makeText(UploadActivity.this, "請先選擇文件", Toast.LENGTH_SHORT).show();            return;        }        //設置文件的媒體類型,image/*表示匹配所有的圖片文件        MediaType mediaType = MediaType.parse("image/*");        MultipartBody.Builder builder = new MultipartBody.Builder();        //文件上傳,此處是關鍵,設置媒體類型為multipart/form-data,表示多種格式的表單數據上傳      builder.setType(MultipartBody.FORM);        //添加上傳的參數username=androidxx        builder.addFormDataPart("username","androidxx");        //添加上傳的文件。文件是從相冊讀取的文件流。        try {            //獲得需要上傳的文件流            InputStream inputStream = getContentResolver().openInputStream(uri);            int len = 0;            byte[] buffer = new byte[1024];            ByteArrayOutputStream baos = new ByteArrayOutputStream();            while((len = inputStream.read(buffer)) != -1) {                baos.write(buffer, 0, len);            }            inputStream.close();            /*             * 添加文件到Builder中。如果要實現多文件同時上傳,可以添加多個addFormDataPart。             * 注意:             * 參數一:上傳的文件的標示,同username。也就是可以在服務器端通過upload找到對應的文件流             * 參數二:文件的名稱。上傳到服務器之后以此名稱命名文件             * 參數三:需要上傳的文件。包含在RequestBody中             * RequestBody.create方法有多個重載的方法,可以選擇不同的數據源。此處選擇的是字節形式(baos.toByteArray())的數據眼。             */builder.addFormDataPart("upload", "test.jpg", RequestBody.create(mediaType, baos.toByteArray()));        } catch (IOException e) {            e.printStackTrace();        }        //創建MultipartBody對象,MultipartBody是RequestBody的子類,用于文件上傳。        MultipartBody multipartBody = builder.build();        Request request = new Request.Builder()                .url("http://192.168.3.4:8080/WebServer/upload.do")//上傳的服務器地址                .post(multipartBody)                .build();        //開始上傳。采用Post異步請求的方式        okHttpClient.newCall(request).enqueue(new Callback() {            @Override            public void onFailure(Call call, IOException e) {                Log.d("androidxx.cn","--" + e.getMessage());                e.printStackTrace();            }            @Override            public void onResponse(Call call, Response response) throws IOException {                //接受到成功的返回結果                if (response.isSuccessful()) {                    Log.d("androidxx.cn","-上傳成功-");                } else {                    Log.d("androidxx.cn","-失敗--" + response.body().string());                }            }        });    }    /**     * 打開相冊,選擇文件后返回     */    private void choosePic() {        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);        intent.setType("image/*");        startActivityForResult(intent,GET_PIC);    }    /**     * 接收選擇的圖片     * @param requestCode     * @param resultCode     * @param data     */    @Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        if (resultCode == RESULT_CANCELED) {            return;        }        //獲得圖片的URI        uri = data.getData();        //通過ContentResolver獲得圖片對象        ContentResolver contentResolver = getContentResolver();        InputStream inputStream = null;        try {            inputStream = contentResolver.openInputStream(uri);        } catch (FileNotFoundException e) {            e.printStackTrace();        }        //將流轉換成圖片,顯示到ImageView中        Bitmap bitmap = BitmapFactory.decodeStream(inputStream);        mShowImage.setImageBitmap(bitmap);    }}復制代碼如上代碼,第37行和第59行是上傳能成功的重點。多文件長傳實現多文件上傳,只需將上面單文件上傳中的builder.addFormDataPart("upload", "test.jpg", RequestBody.create(mediaType, baos.toByteArray()));這一句執行多次,即使用多個addFormDataPart方法添加多個文件,然后就可以同時上傳多個文件了。總結1、文件上傳和下載的過程其實就是一種特殊的Post和Get請求。總體的過程與Post請求和Get請求方式一樣。2、下載相當于一個特殊的Get請求,只是服務器返回的數據格式是文件流。我們也只能通過讀取流來獲得數據。3、上傳相當于一個特殊的Post請求,前面我們說過,Post請求就是傳參數比較特殊和多樣化。文件上傳就是一種特殊的參數傳遞----參數是一個文件。大家在看如上代碼的時候,不要覺得陌生,其實代碼的流程和邏輯同Post和Get請求一樣,只是多了幾行代碼。本案例的android端源碼:Github本案例的上傳服務器配置方式【點擊查看】,上傳服務端源碼:Github     服務器端代碼請閱讀Github中的readme.md文件。服務器端代碼導入工程沒有錯之后,可以將代碼加載到服務器,之后啟動服務器就可以運行。本案例使用的是Tomcat服務器。備注:對于android程序員如果想運行服務器代碼,按照readme.md文檔。然后有不懂的,可以留言。轉載請注明:androidxx.cn最后附上下載效果(注意點擊按鈕開始和停止后下載進度條的變化,實現斷點續傳)。 
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 孟州市| 宜川县| 浙江省| 登封市| 乃东县| 乌鲁木齐市| 连城县| 云龙县| 扎囊县| 新乐市| 和政县| 积石山| 通州市| 宣武区| 土默特右旗| 博白县| 京山县| 额敏县| 台州市| 台北市| 井冈山市| 瓮安县| 巩义市| 福安市| 尼木县| 永清县| 萝北县| 龙海市| 屏山县| 九龙县| 精河县| 天镇县| 历史| 台湾省| 云林县| 株洲县| 靖江市| 潼关县| 常州市| 博罗县| 凌源市|