OkHttp使用+檔案的上傳+斷點續傳

小小時光機發表於2017-05-06

這裡寫圖片描述

  • 普通的Get請求
case R.id.get:
     HttpManager.getInstance().getRequest(getUri,this);
     break;

//方法的回撥  
@Override
    public void onFailure(Call call, IOException e) {//子執行緒
        Log.d("flag", "----------------->onFailure: ");
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        byte[] bytes = response.body().bytes();
        Log.d("flag", "------>onResponse: 獲取圖片位元組長度: " +bytes.length);
        final Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mImageView.setImageBitmap(bitmap);
                Log.d("flag", "------->run: 圖片載入成功");
            }
        });
    }

為了方便呼叫請求,建立單例模式呼叫方法

public void getRequest(String url, Callback callback){
        Request request = new Request.Builder()
                .url(url)
                .build();
        mOkHttpClient.newCall(request).enqueue(callback);
    }

OkHttp是在子執行緒中,注意更新UI操作

  • POST請求
public void postRequest(String url, RequestBody requestBody, Callback callback){
        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)//請求體,引數
                .build();
        mOkHttpClient.newCall(request).enqueue(callback);
    }
case R.id.post:

RequestBody requestBody = new FormBody.Builder()
                        .add("name","michael")
                        .add("age","25")
                        .add("tel","666")
                        .build();
                HttpManager.getInstance().postRequest(postUri,requestBody,this);

此處的回撥方法依舊是Get請求當中的載入圖片

  • 檔案的上傳(post類似,新增請求體)
//上傳資料給伺服器
public void uploadImage(String url, RequestBody uploadBody, Callback callback) {
        Request request = new Request.Builder()
                .url(url)
                .post(uploadBody)
                .build();
        mOkHttpClient.newCall(request).enqueue(callback);
    }

addFormDataPart(請求體)

case upload://上傳資料給伺服器,也是post請求,post請求有請求體,將檔案包裹到請求體,進行上傳
                //multipart/form-data 上傳檔案

                String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath()
                        + File.separator + "icon.jpg";

                File file = new File(path);
                RequestBody body = RequestBody.create(MediaType.parse("image/*"),file);

                RequestBody uploadBody = new MultipartBody.Builder()
                        .addFormDataPart("name","softpo")
                        .addFormDataPart("age","34")
                        .addFormDataPart("tel","0987654321")
                        .addFormDataPart("image","softpo.jpg",body)
                        .build();

                HttpManager.getInstance().uploadImage(uploadUri,uploadBody, new Callback() {
                    @Override
                    public void onFailure(Call call, IOException e) {
                        Log.d("flag", "----------------->onFailure: " +e.getMessage());
                    }
                    @Override
                    public void onResponse(Call call, Response response) throws IOException {
                        Log.d("flag", "----------------->onResponse: " +response.body().string());
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this, "檔案上傳成功", Toast.LENGTH_SHORT).show();
                            }
                        });
                    }
                });
                break;
  • 檔案的斷點續傳

核心:
1.請求網址計算內容的總長度
2.建立執行緒池的物件
3.分配執行緒的執行長度(開始和結束)
4.根據開始和結束-新增addHeader請求頭
5.根據Respose獲取輸入流,讀取寫入檔案
6.介面回撥,載入圖片

case R.id.download_range:
            DownloadManager.getInstance().download(imageUrl,this);
                break;
public class DownloadManager {

    //執行緒池
    public static final int MAX_SIZE = 2;

    private ThreadPoolExecutor mThreadPoolExecutor = new ThreadPoolExecutor(
            MAX_SIZE,
            MAX_SIZE,
            60,
            TimeUnit.MILLISECONDS,
            new SynchronousQueue<Runnable>(),//執行緒管理佇列
            new ThreadFactory() {
                AtomicInteger mAtomicInteger = new AtomicInteger();
                @Override
                public Thread newThread(Runnable r) {
                    //引數二區分執行緒
                    Thread thread =
                            new Thread(r,"Thread Number # "+mAtomicInteger.getAndIncrement());

                    return thread;
                }
            }
    );


    private static DownloadManager ourInstance = new DownloadManager();

    public static DownloadManager getInstance() {
        return ourInstance;
    }

    private DownloadManager() {
    }

    public void download(final String url, final Callback callback){

        HttpManager.getInstance().getRequest(url, new okhttp3.Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                callback.onFailure(e.getMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //要下載內容的總長度
                long contentLength = response.body().contentLength();

                //多執行緒下載
                processDownload(url,contentLength,callback);
            }
        });
    }

    private void processDownload(String url, long contentLength, Callback callback) {
        int length = (int) (contentLength/MAX_SIZE);

        for (int i = 0; i < MAX_SIZE; i++) {//執行兩次

            int start = i*length;
            //奇數:9  4.5  0-4 --- 4+
            //偶數:10  5   0-4 --- 4+
            int end = 0;
            //奇數偶數(類似)
            if(contentLength%2==1){
                end = (i+1)*length;
            }else {//偶數
                end = (i+1)*length-1;
            }
            mThreadPoolExecutor.execute(new DownloadRunnable(url,start,end,callback));
        }
    }
}

根據迴圈每個執行緒去執行start和end

public class DownloadRunnable implements Runnable {

    private String mUrl;
    private int mStart;
    private int mEnd;
    private Callback mCallback;

    public DownloadRunnable(String url, int start, int end, Callback callback) {
        this.mUrl = url;
        this.mStart = start;
        this.mEnd = end;
        this.mCallback = callback;
    }

    @Override
    public void run() {//子執行緒
        Response response = HttpManager.getInstance().asyncGetRangeBytes(mUrl, mStart, mEnd);
        try {
            InputStream is = response.body().byteStream();

            String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
                    .getAbsolutePath() + File.separator
                    + mUrl.substring(mUrl.lastIndexOf("/") + 1);

            File file = new File(path);

            RandomAccessFile randomAccessFile = new RandomAccessFile(file,"rwd");//rwd:可讀可寫可追加
            //!!!
            randomAccessFile.seek(mStart);
            //寫資料
            int len = 0;
            byte[] buf = new byte[1024*8];
            while((len = is.read(buf))!=-1){
                randomAccessFile.write(buf,0,len);
            }
            //回撥
            mCallback.onSuccess(file);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

HttpManager中建立獲取RangeBytes的方法

  public Response asyncGetRangeBytes(String imageUrl,int start,int end){
        //斷點獲取伺服器的資料
        Request request = new Request.Builder()
                .url(imageUrl)
                .addHeader("range","bytes="+start+"-"+end)//請求頭
                .build();
        //execute OkHttp執行聯網請求,下載資料
        try {
            return  mOkHttpClient.newCall(request).execute();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

介面回撥,設定圖片

@Override
    public void onFailure(String message) {
        Log.d("flag", "----------------->onFailure: 多執行緒下載失敗");
    }

    @Override
    public void onSuccess(File file) {
        Log.d("flag", "----------------->onSuccess: 多執行緒下載圖片成功");
        final Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mImageView.setImageBitmap(bitmap);
            }
        });

    }

所用的介面

public interface Callback {
    void onFailure(String message);
    void onSuccess(File file);
}

程式碼已經上傳:

http://download.csdn.net/detail/weixin_37263797/9835223

相關文章