Android HttpUrlConnection網(wǎng)絡(luò)請求、上傳進(jìn)度(分塊上傳)和下載進(jìn)度封裝

想必很多Android開發(fā)人員都在用一些很新型的網(wǎng)絡(luò)框架,但再某些需求中,第三方的網(wǎng)絡(luò)請求框架是需要修改才能實現(xiàn)(比如上傳進(jìn)度實現(xiàn)),這樣導(dǎo)致不僅引入了框架,還要重寫他的方法,項目的體積還變大(雖然大小是KB,但對于Android開發(fā)人員來說項目體積越小越好),言歸正傳我們首先建立一個Demo,建立一個類名為HttpUrlConnectionUtil工具類,先用單利模式把它改進(jìn)一下,我這邊使用的是(內(nèi)部類式)單利模式,還有其他的單利模式,大家可以去嘗試(這里我們簡單看一下HttpUrlConnection的工作流程這樣更方便開發(fā))


image.png

HttpUrlConnection網(wǎng)絡(luò)請求(get和post)

image.png

接下來,創(chuàng)建線程池來管理線程,使用Handler來進(jìn)行線程這間的轉(zhuǎn)換,也可以不用Handler,但為了方便期間使用,接下來看看代碼就知道了,這就就不過多的解釋了,代碼里面都有注釋

import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Message;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class HttpUrlConnectionUtil {
    private HttpUrlConnectionUtil() {

    }

    //創(chuàng)建線程池
    private ExecutorService executorService = Executors.newCachedThreadPool();
    private OnHttpUtilListener onHttpUtilListener;

    private static class Holder {
        private static HttpUrlConnectionUtil INSTANCE = new HttpUrlConnectionUtil();
    }

    public static HttpUrlConnectionUtil getInstance() {
        return Holder.INSTANCE;
    }

    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 1:
                    //成功
                    onHttpUtilListener.onSuccess((String) msg.obj);
                    break;
                case 2:
                    //錯誤
                    onHttpUtilListener.onError((String) msg.obj);
                    break;
                case 3:
                    break;
            }
        }
    };

    public void get(OnHttpUtilListener onHttpUtilListener, final String urlPath) {
        this.onHttpUtilListener = onHttpUtilListener;
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                HttpURLConnection connection = null;
                InputStream inputStream = null;
                try {
                    //獲得URL對象
                    URL url = new URL(urlPath);
                    //返回一個URLConnection對象,它表示到URL所引用的遠(yuǎn)程對象的連接
                    connection = (HttpURLConnection) url.openConnection();
                    // 默認(rèn)為GET
                    connection.setRequestMethod("GET");
                    //不使用緩存
                    connection.setUseCaches(false);
                    //設(shè)置超時時間
                    connection.setConnectTimeout(10000);
                    //設(shè)置讀取超時時間
                    connection.setReadTimeout(10000);
                    //設(shè)置是否從httpUrlConnection讀入,默認(rèn)情況下是true;
                    connection.setDoInput(true);
                    //很多項目需要傳入cookie解開注釋(自行修改)
//                    connection.setRequestProperty("Cookie", "my_cookie");
                    //相應(yīng)碼是否為200
                    if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                        //獲得輸入流
                        inputStream = connection.getInputStream();
                        //包裝字節(jié)流為字符流
                        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                        StringBuilder response = new StringBuilder();
                        String line;
                        while ((line = reader.readLine()) != null) {
                            response.append(line);
                        }
                        //這塊是獲取服務(wù)器返回的cookie(自行修改)
//                        String cookie = connection.getHeaderField("set-cookie");
                        //通過handler更新UI
                        Message message = handler.obtainMessage();
                        message.obj = response.toString();
                        message.what = 1;
                        handler.sendMessage(message);
                    } else {

                        Message message = handler.obtainMessage();
                        message.obj = String.valueOf(connection.getResponseCode());
                        message.what = 2;
                        handler.sendMessage(message);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    Message message = handler.obtainMessage();
                    message.obj = e.getMessage();
                    message.what = 2;
                    handler.sendMessage(message);
                } finally {
                    if (connection != null) {
                        connection.disconnect();
                    }
                    //關(guān)閉讀寫流
                    if (inputStream != null) {
                        try {
                            inputStream.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        };
        //加入線程池
        executorService.execute(runnable);
    }
    public void post(OnHttpUtilListener onHttpUtilListener, final String urlPath, final Map<String, String> params) {
        this.onHttpUtilListener = onHttpUtilListener;
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                HttpURLConnection connection = null;
                InputStream inputStream = null;
                OutputStream outputStream = null;
                StringBuffer body = getParamString(params);
                byte[] data = body.toString().getBytes();
                try {
                    //獲得URL對象
                    URL url = new URL(urlPath);
                    //返回一個URLConnection對象,它表示到URL所引用的遠(yuǎn)程對象的連接
                    connection = (HttpURLConnection) url.openConnection();
                    // 默認(rèn)為GET
                    connection.setRequestMethod("POST");
                    //不使用緩存
                    connection.setUseCaches(false);
                    //設(shè)置超時時間
                    connection.setConnectTimeout(10000);
                    //設(shè)置讀取超時時間
                    connection.setReadTimeout(10000);
                    //設(shè)置是否從httpUrlConnection讀入,默認(rèn)情況下是true;
                    connection.setDoInput(true);
                    //設(shè)置為true后才能寫入?yún)?shù)
                    connection.setDoOutput(true);
                    //post請求需要設(shè)置標(biāo)頭
                    connection.setRequestProperty("Connection", "Keep-Alive");
                    connection.setRequestProperty("Charset", "UTF-8");
                    //表單參數(shù)類型標(biāo)頭
                    connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                    //很多項目需要傳入cookie解開注釋(自行修改)
//                    connection.setRequestProperty("Cookie", "my_cookie");
                    //獲取寫入流
                    outputStream=connection.getOutputStream();
                    //寫入表單參數(shù)
                    outputStream.write(data);
                    //相應(yīng)碼是否為200
                    if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                        //獲得輸入流
                        inputStream = connection.getInputStream();
                        //包裝字節(jié)流為字符流
                        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                        StringBuilder response = new StringBuilder();
                        String line;
                        while ((line = reader.readLine()) != null) {
                            response.append(line);
                        }
                        //這塊是獲取服務(wù)器返回的cookie(自行修改)
//                        String cookie = connection.getHeaderField("set-cookie");
                        //通過handler更新UI
                        Message message = handler.obtainMessage();
                        message.obj = response.toString();
                        message.what = 1;
                        handler.sendMessage(message);
                    } else {

                        Message message = handler.obtainMessage();
                        message.obj = String.valueOf(connection.getResponseCode());
                        message.what = 2;
                        handler.sendMessage(message);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    Message message = handler.obtainMessage();
                    message.obj = e.getMessage();
                    message.what = 2;
                    handler.sendMessage(message);
                } finally {
                    if (connection != null) {
                        connection.disconnect();
                    }
                    //關(guān)閉讀寫流
                    if (inputStream != null) {
                        try {
                            inputStream.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        };
        //加入線程池
        executorService.execute(runnable);
    }

    //post請求參數(shù)
    private StringBuffer getParamString(Map<String, String> params){
        StringBuffer result = new StringBuffer();
        Iterator<Map.Entry<String, String>> iterator = params.entrySet().iterator();
        while (iterator.hasNext()){
            Map.Entry<String, String> param = iterator.next();
            String key = param.getKey();
            String value = param.getValue();
            result.append(key).append('=').append(value);
            if (iterator.hasNext()){
                result.append('&');
            }
        }
        return result;
    }
    //回調(diào)接口
    interface OnHttpUtilListener {
        void onError(String e);

        void onSuccess(String json);
    }
}

里面還可以繼續(xù)提取封裝,這里我就不操作了,有興趣的朋友,可以進(jìn)化代碼。
接下來看看如果使用


image.png

用起來很簡單對不對,也可以用泛型封裝,再用第三方Gson,這樣在項目用起來很方便的。既然簡單請求已經(jīng)上手了,那我進(jìn)階一下吧,估計下面才是大家想找到東西~~~。

HttpUrlConnection上傳進(jìn)度(分塊上傳)和下載進(jìn)度

既然說到上傳下載我們必然離不開異步,這里我們就不使用Handler雖然它很強(qiáng)大也可以實現(xiàn),但我們有更方便的解決方案。那就是AsyncTask用它來實現(xiàn)線程直接的調(diào)度
接下來需要創(chuàng)建一個類名為HttpUrlConnectionAsyncTask工具類,代碼如下

import android.os.AsyncTask;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * 括號里的類型
 * 第一個代表doInBackground方法需要傳入的類型
 * 第二個代表onProgressUpdate方法需要傳入的類型
 * 第一個代表onPostExecute方法需要傳入的類型
 */
public class HttpUrlConnectionAsyncTask extends AsyncTask<Integer, Integer, String> {

    private Integer UPLOAD = 1;

    private OnHttpProgressUtilListener onHttpProgressUtilListener;
    private String urlPath;
    private String filePath;

    public void uploadFile(OnHttpProgressUtilListener onHttpProgressUtilListener, String urlPath, String filePath) {
        this.urlPath = urlPath;
        this.filePath = filePath;
        //調(diào)用doInBackground方法(方法里面是異步執(zhí)行)
        execute(UPLOAD);
    }

    public void downloadFile(OnHttpProgressUtilListener onHttpProgressUtilListener, String urlPath, String filePath) {
        this.urlPath = urlPath;
        this.filePath = filePath;
        //調(diào)用doInBackground方法(方法里面是異步執(zhí)行)
        execute(2);
    }

    @Override
    protected String doInBackground(Integer... integers) {
        return integers[0].equals(UPLOAD) ? upload() : download();
    }

    private String upload() {
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        OutputStream outputStream = null;
        File file = new File(filePath);

        String result = "";
        try {
            //獲得URL對象
            URL url = new URL(urlPath);
            //返回一個URLConnection對象,它表示到URL所引用的遠(yuǎn)程對象的連接
            connection = (HttpURLConnection) url.openConnection();
            // 默認(rèn)為GET
            connection.setRequestMethod("POST");
            //不使用緩存
            connection.setUseCaches(false);
            //設(shè)置超時時間
            connection.setConnectTimeout(10000);
            //設(shè)置讀取超時時間
            connection.setReadTimeout(10000);
            //設(shè)置是否從httpUrlConnection讀入,默認(rèn)情況下是true;
            connection.setDoInput(true);
            //設(shè)置為true后才能寫入?yún)?shù)
            connection.setDoOutput(true);
            //設(shè)置為true后才能寫入?yún)?shù)
            connection.setRequestProperty("Content-Type", "multipart/form-data");
            connection.setRequestProperty("Content-Length", String.valueOf(file.length()));
            outputStream = new DataOutputStream(connection.getOutputStream());
            DataInputStream dataInputStream = new DataInputStream(new FileInputStream(file));
            int count = 0;
            // 計算上傳進(jìn)度
            Long progress = 0L;
            byte[] bufferOut = new byte[2048];
            while ((count = dataInputStream.read(bufferOut)) != -1) {
                outputStream.write(bufferOut, 0, count);
                progress += count;
                //換算進(jìn)度
                double d = (new BigDecimal(progress / (double) file.length()).setScale(2, BigDecimal.ROUND_HALF_UP)).doubleValue();
                double d1 = d * 100;
                //傳入的值為1-100
                onProgressUpdate((int) d1);
            }
            dataInputStream.close();
            //寫入?yún)?shù)
            if (connection.getResponseCode()==HttpURLConnection.HTTP_OK){
                //獲得輸入流
                inputStream = connection.getInputStream();
                //包裝字節(jié)流為字符流
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                StringBuilder response = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                result=response.toString();
            }else {
                result = String.valueOf(connection.getResponseCode());
            }
        } catch (Exception e) {
            e.printStackTrace();
            onCancelled(e.getMessage());
        } finally {
            //關(guān)閉
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                connection.disconnect();
            }
        }
        return result;
    }

    private String download() {
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        OutputStream outputStream = null;
        String result = "";
        try {
            //獲得URL對象
            URL url = new URL(urlPath);
            //返回一個URLConnection對象,它表示到URL所引用的遠(yuǎn)程對象的連接
            connection = (HttpURLConnection) url.openConnection();
            //建立實際鏈接
            connection.connect();
            inputStream=connection.getInputStream();
            //獲取文件長度
            Double size = (double) connection.getContentLength();

            outputStream = new FileOutputStream(filePath);
            int count = 0;
            // 計算上傳進(jìn)度
            Long progress = 0L;
            byte[]  bytes= new byte[2048];
            while ((count=inputStream.read(bytes))!=-1){
                outputStream.write(bytes,0,count);
                //換算進(jìn)度
                double d = (new BigDecimal(progress / size).setScale(2, BigDecimal.ROUND_HALF_UP)).doubleValue();
                double d1 = d * 100;
                //傳入的值為1-100
                onProgressUpdate((int) d1);
            }
            result = "下載成功";
        } catch (Exception e) {
            e.printStackTrace();
            onCancelled(e.getMessage());
        } finally {
            //關(guān)閉
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                connection.disconnect();
            }
        }
        return result;
    }


    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        onHttpProgressUtilListener.onProgress(values[0]);
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        onHttpProgressUtilListener.onSuccess(s);
    }

    @Override
    protected void onCancelled(String s) {
        super.onCancelled(s);
        onHttpProgressUtilListener.onError(s);
    }

    interface OnHttpProgressUtilListener {
        void onError(String e);

        void onProgress(Integer length);

        void onSuccess(String json);
    }
}

上傳和下載已經(jīng)分裝好了,在進(jìn)度換算中這里面需要注意,因為用Double類型比較好換算進(jìn)度,BigDecimal保留了兩位小數(shù),
代碼里,doInBackground是異步執(zhí)行的,onPostExecute(上傳和下載結(jié)果)和onProgressUpdate(上傳和下載進(jìn)度)它是調(diào)度到主線程了。下面我們來說說分塊上傳該怎么實現(xiàn),因為在上傳項目中有一些大的項目,服務(wù)器那邊做了可以分塊上傳,這個時候Android該怎么實現(xiàn)上傳。

HttpUrlConnection分塊上傳

首先需要一個方法來處理分塊

private byte[] getBlock(Long offset, File file, int blockSize) {
        byte[] result = new byte[blockSize];
        RandomAccessFile accessFile = null;
        try {
            accessFile = new RandomAccessFile(file, "r");
            //將文件記錄指針定位到pos位置
            accessFile.seek(offset);
            int readSize = accessFile.read(result);
            if (readSize == -1) {
                return null;
            } else if (readSize == blockSize) {
                return result;
            } else {
                byte[] tmpByte = new byte[readSize];
                System.arraycopy(result, 0, tmpByte, 0, readSize);
                return tmpByte;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (accessFile != null) {
                try {
                    accessFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

這里參數(shù)offset記錄文件上一次讀寫的位置,blockSize代表每塊大小,接下來咱們看看如果實現(xiàn)網(wǎng)絡(luò)請求


    private String filePath;
    private byte[] data;
    public void uploadFileBlock(OnHttpProgressUtilListener onHttpProgressUtilListener, String urlPath, byte[] data) {
        this.urlPath = urlPath;
        this.data = data;
        //調(diào)用doInBackground方法(方法里面是異步執(zhí)行)
    }
private String uploadBlock() {
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        OutputStream outputStream = null;

        String result = "";
        try {
            //獲得URL對象
            URL url = new URL(urlPath);
            //返回一個URLConnection對象,它表示到URL所引用的遠(yuǎn)程對象的連接
            connection = (HttpURLConnection) url.openConnection();
            // 默認(rèn)為GET
            connection.setRequestMethod("POST");
            //不使用緩存
            connection.setUseCaches(false);
            //設(shè)置超時時間
            connection.setConnectTimeout(10000);
            //設(shè)置讀取超時時間
            connection.setReadTimeout(10000);
            //設(shè)置是否從httpUrlConnection讀入,默認(rèn)情況下是true;
            connection.setDoInput(true);
            //設(shè)置為true后才能寫入?yún)?shù)
            connection.setDoOutput(true);
            //設(shè)置為true后才能寫入?yún)?shù)
            connection.setRequestProperty("Content-Type", "multipart/form-data");
            //這里需要改動
            connection.setRequestProperty("Content-Length", String.valueOf(data.length));
            outputStream = new DataOutputStream(connection.getOutputStream());
            //這塊需要改為ByteArrayInputStream寫入流
            ByteArrayInputStream inputStreamByte = new ByteArrayInputStream(data);
            int count = 0;
            // 計算上傳進(jìn)度
            Integer progress = 0;
            byte[] bufferOut = new byte[2048];
            while ((count = inputStreamByte.read(bufferOut)) != -1) {
                outputStream.write(bufferOut, 0, count);
                progress += count;
                onProgressUpdate(progress);
            }
            inputStreamByte.close();
            //寫入?yún)?shù)
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                //獲得輸入流
                inputStream = connection.getInputStream();
                //包裝字節(jié)流為字符流
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                StringBuilder response = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                result = response.toString();
            } else {
                result = String.valueOf(connection.getResponseCode());
            }
        } catch (Exception e) {
            e.printStackTrace();
            onCancelled(e.getMessage());
        } finally {
            //關(guān)閉
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                connection.disconnect();
            }
        }
        return result;
    }

這里我們傳的是byte[]而不是文件路徑了,我們下面看看整個類變成什么樣了

import android.os.AsyncTask;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * 括號里的類型
 * 第一個代表doInBackground方法需要傳入的類型
 * 第二個代表onProgressUpdate方法需要傳入的類型
 * 第一個代表onPostExecute方法需要傳入的類型
 */
public class HttpUrlConnectionAsyncTask extends AsyncTask<Integer, Integer, String> {

    private Integer UPLOAD = 1;
    private Integer DOWNLOAD = 2;


    private OnHttpProgressUtilListener onHttpProgressUtilListener;
    private String urlPath;
    private String filePath;
    private byte[] data;
    public void uploadFileBlock(OnHttpProgressUtilListener onHttpProgressUtilListener, String urlPath, byte[] data) {
        this.urlPath = urlPath;
        this.data = data;
        //調(diào)用doInBackground方法(方法里面是異步執(zhí)行)
        execute(UPLOAD);
    }

    public void uploadFile(OnHttpProgressUtilListener onHttpProgressUtilListener, String urlPath, String filePath) {
        this.urlPath = urlPath;
        this.filePath = filePath;
        //調(diào)用doInBackground方法(方法里面是異步執(zhí)行)
        execute(UPLOAD);
    }


    public void downloadFile(OnHttpProgressUtilListener onHttpProgressUtilListener, String urlPath, String filePath) {
        this.urlPath = urlPath;
        this.filePath = filePath;
        //調(diào)用doInBackground方法(方法里面是異步執(zhí)行)
        execute(2);
    }

    @Override
    protected String doInBackground(Integer... integers) {
        String result;
        if (integers[0].equals(UPLOAD)) {
            result = upload();
        } else if (integers[0].equals(DOWNLOAD)) {
            result = download();
        } else {
            result = uploadBlock();
        }
        return result;
    }

    private String upload() {
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        OutputStream outputStream = null;
        File file = new File(filePath);

        String result = "";
        try {
            //獲得URL對象
            URL url = new URL(urlPath);
            //返回一個URLConnection對象,它表示到URL所引用的遠(yuǎn)程對象的連接
            connection = (HttpURLConnection) url.openConnection();
            // 默認(rèn)為GET
            connection.setRequestMethod("POST");
            //不使用緩存
            connection.setUseCaches(false);
            //設(shè)置超時時間
            connection.setConnectTimeout(10000);
            //設(shè)置讀取超時時間
            connection.setReadTimeout(10000);
            //設(shè)置是否從httpUrlConnection讀入,默認(rèn)情況下是true;
            connection.setDoInput(true);
            //設(shè)置為true后才能寫入?yún)?shù)
            connection.setDoOutput(true);
            //設(shè)置為true后才能寫入?yún)?shù)
            connection.setRequestProperty("Content-Type", "multipart/form-data");
            connection.setRequestProperty("Content-Length", String.valueOf(file.length()));
            outputStream = new DataOutputStream(connection.getOutputStream());
            DataInputStream dataInputStream = new DataInputStream(new FileInputStream(file));
            int count = 0;
            // 計算上傳進(jìn)度
            Long progress = 0L;
            byte[] bufferOut = new byte[2048];
            while ((count = dataInputStream.read(bufferOut)) != -1) {
                outputStream.write(bufferOut, 0, count);
                progress += count;
                //換算進(jìn)度
                double d = (new BigDecimal(progress / (double) file.length()).setScale(2, BigDecimal.ROUND_HALF_UP)).doubleValue();
                double d1 = d * 100;
                //傳入的值為1-100
                onProgressUpdate((int) d1);
            }
            dataInputStream.close();
            //寫入?yún)?shù)
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                //獲得輸入流
                inputStream = connection.getInputStream();
                //包裝字節(jié)流為字符流
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                StringBuilder response = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                result = response.toString();
            } else {
                result = String.valueOf(connection.getResponseCode());
            }
        } catch (Exception e) {
            e.printStackTrace();
            onCancelled(e.getMessage());
        } finally {
            //關(guān)閉
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                connection.disconnect();
            }
        }
        return result;
    }

    private String uploadBlock() {
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        OutputStream outputStream = null;

        String result = "";
        try {
            //獲得URL對象
            URL url = new URL(urlPath);
            //返回一個URLConnection對象,它表示到URL所引用的遠(yuǎn)程對象的連接
            connection = (HttpURLConnection) url.openConnection();
            // 默認(rèn)為GET
            connection.setRequestMethod("POST");
            //不使用緩存
            connection.setUseCaches(false);
            //設(shè)置超時時間
            connection.setConnectTimeout(10000);
            //設(shè)置讀取超時時間
            connection.setReadTimeout(10000);
            //設(shè)置是否從httpUrlConnection讀入,默認(rèn)情況下是true;
            connection.setDoInput(true);
            //設(shè)置為true后才能寫入?yún)?shù)
            connection.setDoOutput(true);
            //設(shè)置為true后才能寫入?yún)?shù)
            connection.setRequestProperty("Content-Type", "multipart/form-data");
            //這里需要改動
            connection.setRequestProperty("Content-Length", String.valueOf(data.length));
            outputStream = new DataOutputStream(connection.getOutputStream());
            //這塊需要改為ByteArrayInputStream寫入流
            ByteArrayInputStream inputStreamByte = new ByteArrayInputStream(data);
            int count = 0;
            // 計算上傳進(jìn)度
            Integer progress = 0;
            byte[] bufferOut = new byte[2048];
            while ((count = inputStreamByte.read(bufferOut)) != -1) {
                outputStream.write(bufferOut, 0, count);
                progress += count;
                onProgressUpdate(progress);
            }
            inputStreamByte.close();
            //寫入?yún)?shù)
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                //獲得輸入流
                inputStream = connection.getInputStream();
                //包裝字節(jié)流為字符流
                BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                StringBuilder response = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    response.append(line);
                }
                result = response.toString();
            } else {
                result = String.valueOf(connection.getResponseCode());
            }
        } catch (Exception e) {
            e.printStackTrace();
            onCancelled(e.getMessage());
        } finally {
            //關(guān)閉
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                connection.disconnect();
            }
        }
        return result;
    }

    private String download() {
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        OutputStream outputStream = null;
        String result = "";
        try {
            //獲得URL對象
            URL url = new URL(urlPath);
            //返回一個URLConnection對象,它表示到URL所引用的遠(yuǎn)程對象的連接
            connection = (HttpURLConnection) url.openConnection();
            //建立實際鏈接
            connection.connect();
            inputStream = connection.getInputStream();
            //獲取文件長度
            Double size = (double) connection.getContentLength();

            outputStream = new FileOutputStream(filePath);
            int count = 0;
            // 計算上傳進(jìn)度
            Long progress = 0L;
            byte[] bytes = new byte[2048];
            while ((count = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, count);
                //換算進(jìn)度
                double d = (new BigDecimal(progress / size).setScale(2, BigDecimal.ROUND_HALF_UP)).doubleValue();
                double d1 = d * 100;
                //傳入的值為1-100
                onProgressUpdate((int) d1);
            }
            result = "下載成功";
        } catch (Exception e) {
            e.printStackTrace();
            onCancelled(e.getMessage());
        } finally {
            //關(guān)閉
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                connection.disconnect();
            }
        }
        return result;
    }


    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        onHttpProgressUtilListener.onProgress(values[0]);
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        onHttpProgressUtilListener.onSuccess(s);
    }

    @Override
    protected void onCancelled(String s) {
        super.onCancelled(s);
        onHttpProgressUtilListener.onError(s);
    }

    interface OnHttpProgressUtilListener {
        void onError(String e);

        void onProgress(Integer length);

        void onSuccess(String json);
    }
}

下面我們看看如果使用分塊上傳,使用分塊上傳必須服務(wù)器支持分塊上傳才可以

int chuncks=0;//流塊
    double chunckProgress=0.0;//進(jìn)度
    private void upload(){
        //每一塊大小
        int blockLength=1024*1024*2;
        File file = new File("文件路徑");
        final long fileSize=file.length();
        //當(dāng)前第幾塊
        int chunck = 0;
        //換算總共分多少塊
        if (file.length() % blockLength == 0L) {
            chuncks= (int) (file.length() / blockLength);
        } else {
            chuncks= (int) (file.length()/ blockLength + 1);
        }
        while (chunck<chuncks){
            //換算出第幾塊的byte[]
            byte[] block = getBlock((long) (chunck * blockLength), file, blockLength);
            new HttpUrlConnectionAsyncTask().uploadFileBlock(new HttpUrlConnectionAsyncTask.OnHttpProgressUtilListener() {

                @Override
                public void onError(String e) {

                }

                @Override
                public void onProgress(Integer progress) {
                    //換算進(jìn)度
                    double d = (new BigDecimal(progress / fileSize).setScale(2, BigDecimal.ROUND_HALF_UP)).doubleValue();
                    int pro= (int) (d*100);
                    //這個就是上傳進(jìn)度,已經(jīng)換算為1-100
                    Log.d(TAG, "onProgress: "+pro);
                }

                @Override
                public void onSuccess(String json) {
                    //上傳成功

                }
            },"上傳URL 需要傳入當(dāng)前塊chunck和總塊數(shù)chuncks參數(shù),需接口支持才行",block);
            chunck++;
        }
    }

這樣就上傳成功了,以后遇到上傳下載都可以這樣用,但也可以選擇第三方網(wǎng)絡(luò)請求框架,各有所長

這個是項目地址大家可以作為參考
git :https://github.com/GuoLiangGod/HttpUrlConnectionDemo
這篇文件,希望對大家又幫助,如果遇到問題可以留言

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容