Android HttpUrlConnection网络请求、上传进度(分块上传)和下载进度封装

想必很多Android开发人员都在用一些很新型的网络框架,但再某些需求中,第三方的网络请求框架是需要修改才能实现(比如上传进度实现),这样导致不仅引入了框架,还要重写他的方法,项目的体积还变大(虽然大小是KB,但对于Android开发人员来说项目体积越小越好),言归正传我们首先建立一个Demo,建立一个类名为HttpUrlConnectionUtil工具类,先用单利模式把它改进一下,我这边使用的是(内部类式)单利模式,还有其他的单利模式,大家可以去尝试(这里我们简单看一下HttpUrlConnection的工作流程这样更方便开发)


image.png

HttpUrlConnection网络请求(get和post)

image.png

接下来,创建线程池来管理线程,使用Handler来进行线程这间的转换,也可以不用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() {

    }

    //创建线程池
    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所引用的远程对象的连接
                    connection = (HttpURLConnection) url.openConnection();
                    // 默认为GET
                    connection.setRequestMethod("GET");
                    //不使用缓存
                    connection.setUseCaches(false);
                    //设置超时时间
                    connection.setConnectTimeout(10000);
                    //设置读取超时时间
                    connection.setReadTimeout(10000);
                    //设置是否从httpUrlConnection读入,默认情况下是true;
                    connection.setDoInput(true);
                    //很多项目需要传入cookie解开注释(自行修改)
//                    connection.setRequestProperty("Cookie", "my_cookie");
                    //相应码是否为200
                    if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                        //获得输入流
                        inputStream = connection.getInputStream();
                        //包装字节流为字符流
                        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                        StringBuilder response = new StringBuilder();
                        String line;
                        while ((line = reader.readLine()) != null) {
                            response.append(line);
                        }
                        //这块是获取服务器返回的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();
                    }
                    //关闭读写流
                    if (inputStream != null) {
                        try {
                            inputStream.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        };
        //加入线程池
        executorService.execute(runnable);
    }
    public void post(OnHttpUtilListener onHttpUtilListener, final String urlPath, final Map 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所引用的远程对象的连接
                    connection = (HttpURLConnection) url.openConnection();
                    // 默认为GET
                    connection.setRequestMethod("POST");
                    //不使用缓存
                    connection.setUseCaches(false);
                    //设置超时时间
                    connection.setConnectTimeout(10000);
                    //设置读取超时时间
                    connection.setReadTimeout(10000);
                    //设置是否从httpUrlConnection读入,默认情况下是true;
                    connection.setDoInput(true);
                    //设置为true后才能写入参数
                    connection.setDoOutput(true);
                    //post请求需要设置标头
                    connection.setRequestProperty("Connection", "Keep-Alive");
                    connection.setRequestProperty("Charset", "UTF-8");
                    //表单参数类型标头
                    connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                    //很多项目需要传入cookie解开注释(自行修改)
//                    connection.setRequestProperty("Cookie", "my_cookie");
                    //获取写入流
                    outputStream=connection.getOutputStream();
                    //写入表单参数
                    outputStream.write(data);
                    //相应码是否为200
                    if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                        //获得输入流
                        inputStream = connection.getInputStream();
                        //包装字节流为字符流
                        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                        StringBuilder response = new StringBuilder();
                        String line;
                        while ((line = reader.readLine()) != null) {
                            response.append(line);
                        }
                        //这块是获取服务器返回的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();
                    }
                    //关闭读写流
                    if (inputStream != null) {
                        try {
                            inputStream.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        };
        //加入线程池
        executorService.execute(runnable);
    }

    //post请求参数
    private StringBuffer getParamString(Map params){
        StringBuffer result = new StringBuffer();
        Iterator> iterator = params.entrySet().iterator();
        while (iterator.hasNext()){
            Map.Entry param = iterator.next();
            String key = param.getKey();
            String value = param.getValue();
            result.append(key).append('=').append(value);
            if (iterator.hasNext()){
                result.append('&');
            }
        }
        return result;
    }
    //回调接口
    interface OnHttpUtilListener {
        void onError(String e);

        void onSuccess(String json);
    }
}

里面还可以继续提取封装,这里我就不操作了,有兴趣的朋友,可以进化代码。
接下来看看如果使用


image.png

用起来很简单对不对,也可以用泛型封装,再用第三方Gson,这样在项目用起来很方便的。既然简单请求已经上手了,那我进阶一下吧,估计下面才是大家想找到东西~~~。

HttpUrlConnection上传进度(分块上传)和下载进度

既然说到上传下载我们必然离不开异步,这里我们就不使用Handler虽然它很强大也可以实现,但我们有更方便的解决方案。那就是AsyncTask用它来实现线程直接的调度
接下来需要创建一个类名为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 {

    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;
        //调用doInBackground方法(方法里面是异步执行)
        execute(UPLOAD);
    }

    public void downloadFile(OnHttpProgressUtilListener onHttpProgressUtilListener, String urlPath, String filePath) {
        this.urlPath = urlPath;
        this.filePath = filePath;
        //调用doInBackground方法(方法里面是异步执行)
        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所引用的远程对象的连接
            connection = (HttpURLConnection) url.openConnection();
            // 默认为GET
            connection.setRequestMethod("POST");
            //不使用缓存
            connection.setUseCaches(false);
            //设置超时时间
            connection.setConnectTimeout(10000);
            //设置读取超时时间
            connection.setReadTimeout(10000);
            //设置是否从httpUrlConnection读入,默认情况下是true;
            connection.setDoInput(true);
            //设置为true后才能写入参数
            connection.setDoOutput(true);
            //设置为true后才能写入参数
            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;
            // 计算上传进度
            Long progress = 0L;
            byte[] bufferOut = new byte[2048];
            while ((count = dataInputStream.read(bufferOut)) != -1) {
                outputStream.write(bufferOut, 0, count);
                progress += count;
                //换算进度
                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();
            //写入参数
            if (connection.getResponseCode()==HttpURLConnection.HTTP_OK){
                //获得输入流
                inputStream = connection.getInputStream();
                //包装字节流为字符流
                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 {
            //关闭
            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所引用的远程对象的连接
            connection = (HttpURLConnection) url.openConnection();
            //建立实际链接
            connection.connect();
            inputStream=connection.getInputStream();
            //获取文件长度
            Double size = (double) connection.getContentLength();

            outputStream = new FileOutputStream(filePath);
            int count = 0;
            // 计算上传进度
            Long progress = 0L;
            byte[]  bytes= new byte[2048];
            while ((count=inputStream.read(bytes))!=-1){
                outputStream.write(bytes,0,count);
                //换算进度
                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 {
            //关闭
            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);
    }
}

上传和下载已经分装好了,在进度换算中这里面需要注意,因为用Double类型比较好换算进度,BigDecimal保留了两位小数,
代码里,doInBackground是异步执行的,onPostExecute(上传和下载结果)和onProgressUpdate(上传和下载进度)它是调度到主线程了。下面我们来说说分块上传该怎么实现,因为在上传项目中有一些大的项目,服务器那边做了可以分块上传,这个时候Android该怎么实现上传。

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

这里参数offset记录文件上一次读写的位置,blockSize代表每块大小,接下来咱们看看如果实现网络请求


    private String filePath;
    private byte[] data;
    public void uploadFileBlock(OnHttpProgressUtilListener onHttpProgressUtilListener, String urlPath, byte[] data) {
        this.urlPath = urlPath;
        this.data = data;
        //调用doInBackground方法(方法里面是异步执行)
    }
private String uploadBlock() {
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        OutputStream outputStream = null;

        String result = "";
        try {
            //获得URL对象
            URL url = new URL(urlPath);
            //返回一个URLConnection对象,它表示到URL所引用的远程对象的连接
            connection = (HttpURLConnection) url.openConnection();
            // 默认为GET
            connection.setRequestMethod("POST");
            //不使用缓存
            connection.setUseCaches(false);
            //设置超时时间
            connection.setConnectTimeout(10000);
            //设置读取超时时间
            connection.setReadTimeout(10000);
            //设置是否从httpUrlConnection读入,默认情况下是true;
            connection.setDoInput(true);
            //设置为true后才能写入参数
            connection.setDoOutput(true);
            //设置为true后才能写入参数
            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;
            // 计算上传进度
            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();
            //写入参数
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                //获得输入流
                inputStream = connection.getInputStream();
                //包装字节流为字符流
                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 {
            //关闭
            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 {

    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;
        //调用doInBackground方法(方法里面是异步执行)
        execute(UPLOAD);
    }

    public void uploadFile(OnHttpProgressUtilListener onHttpProgressUtilListener, String urlPath, String filePath) {
        this.urlPath = urlPath;
        this.filePath = filePath;
        //调用doInBackground方法(方法里面是异步执行)
        execute(UPLOAD);
    }


    public void downloadFile(OnHttpProgressUtilListener onHttpProgressUtilListener, String urlPath, String filePath) {
        this.urlPath = urlPath;
        this.filePath = filePath;
        //调用doInBackground方法(方法里面是异步执行)
        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所引用的远程对象的连接
            connection = (HttpURLConnection) url.openConnection();
            // 默认为GET
            connection.setRequestMethod("POST");
            //不使用缓存
            connection.setUseCaches(false);
            //设置超时时间
            connection.setConnectTimeout(10000);
            //设置读取超时时间
            connection.setReadTimeout(10000);
            //设置是否从httpUrlConnection读入,默认情况下是true;
            connection.setDoInput(true);
            //设置为true后才能写入参数
            connection.setDoOutput(true);
            //设置为true后才能写入参数
            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;
            // 计算上传进度
            Long progress = 0L;
            byte[] bufferOut = new byte[2048];
            while ((count = dataInputStream.read(bufferOut)) != -1) {
                outputStream.write(bufferOut, 0, count);
                progress += count;
                //换算进度
                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();
            //写入参数
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                //获得输入流
                inputStream = connection.getInputStream();
                //包装字节流为字符流
                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 {
            //关闭
            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所引用的远程对象的连接
            connection = (HttpURLConnection) url.openConnection();
            // 默认为GET
            connection.setRequestMethod("POST");
            //不使用缓存
            connection.setUseCaches(false);
            //设置超时时间
            connection.setConnectTimeout(10000);
            //设置读取超时时间
            connection.setReadTimeout(10000);
            //设置是否从httpUrlConnection读入,默认情况下是true;
            connection.setDoInput(true);
            //设置为true后才能写入参数
            connection.setDoOutput(true);
            //设置为true后才能写入参数
            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;
            // 计算上传进度
            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();
            //写入参数
            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                //获得输入流
                inputStream = connection.getInputStream();
                //包装字节流为字符流
                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 {
            //关闭
            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所引用的远程对象的连接
            connection = (HttpURLConnection) url.openConnection();
            //建立实际链接
            connection.connect();
            inputStream = connection.getInputStream();
            //获取文件长度
            Double size = (double) connection.getContentLength();

            outputStream = new FileOutputStream(filePath);
            int count = 0;
            // 计算上传进度
            Long progress = 0L;
            byte[] bytes = new byte[2048];
            while ((count = inputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, count);
                //换算进度
                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 {
            //关闭
            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);
    }
}

下面我们看看如果使用分块上传,使用分块上传必须服务器支持分块上传才可以

int chuncks=0;//流块
    double chunckProgress=0.0;//进度
    private void upload(){
        //每一块大小
        int blockLength=1024*1024*2;
        File file = new File("文件路径");
        final long fileSize=file.length();
        //当前第几块
        int chunck = 0;
        //换算总共分多少块
        if (file.length() % blockLength == 0L) {
            chuncks= (int) (file.length() / blockLength);
        } else {
            chuncks= (int) (file.length()/ blockLength + 1);
        }
        while (chunck

这样就上传成功了,以后遇到上传下载都可以这样用,但也可以选择第三方网络请求框架,各有所长

这个是项目地址大家可以作为参考
git :https://github.com/GuoLiangGod/HttpUrlConnectionDemo
这篇文件,希望对大家又帮助,如果遇到问题可以留言

你可能感兴趣的:(Android HttpUrlConnection网络请求、上传进度(分块上传)和下载进度封装)