天天看点

Http协议Get与Post请求方式+响应码+断点续传+MVC架构

Get请求方式

Get主要用于文件下载

将下载文件的代码封装在线程中,通过Handler去实现功能,代码如下:

public class DownloadThread extends Thread {

    String u;
    String path;
    Handler handler;

    public DownloadThread(Handler handler, String u, String path) {
        this.u = u;
        this.path = path;
        this.handler = handler;
    }

    @Override
    public void run() {
        super.run();
        InputStream is = null;
        FileOutputStream fileOutputStream = null;
        try {
            URL url = new URL(u);
            HttpURLConnection http = (HttpURLConnection) url.openConnection();

            int contentLength = http.getContentLength();
            Message message1 = Message.obtain();
            message1.what=101;
            message1.obj=contentLength;
            handler.sendMessage(message1);

            if (http.getResponseCode()==200) {
                is = http.getInputStream();
                fileOutputStream = new FileOutputStream(path);
                byte[] bytes = new byte[1024];
                int len = 0;
                int count=0;
                while ((len=is.read(bytes))!=-1) {
                    count+=len;
                    Thread.sleep(100);
                    fileOutputStream.write(bytes,0,len);
                    Message message2 = Message.obtain();
                    message2.what=100;
                    message2.obj=count;
                    handler.sendMessage(message2);
                }
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (is!=null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fileOutputStream!=null){
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
           

Post请求方式

Post主要用于上传

上传文件:post请求

  1. 设置请求头信息:

    Content-Length:请求体的长度

    Content-Type:multipart/form-data; boundary=7e324741816d4

  2. 请求体:

    第一部分 要有换行

    -----------------------------7e324741816d4

    Content-Disposition: form-data; name=“file”; filename=“上传到服务器的名字”

    Content-Type: media/mp4或者media/mp3或者image/mp3或者image/png

    空行

    第二部分 需要上传的文件:边读边写

将上传文件的代码封装在线程中,通过Handler去实现功能,代码如下:

public class UploadThread extends Thread {

    String u;
    String path;
    Handler handler;
    String filname;

    public UploadThread(Handler handler, String u, String path,String filname) {
        this.handler = handler;
        this.path = path;
        this.u = u;
        this.filname = filname;
    }

    @Override
    public void run() {
        super.run();
        OutputStream os = null;
        FileInputStream fileInputStream = null;
        int filelenth = 0;
        try {
//          添加响应体
            StringBuffer sb = new StringBuffer();
            sb.append("-----------------------------7e324741816d4"+"\r\n");
            sb.append("Content-Disposition: form-data; name=\"file\"; filename=\""+filname+"\"\r\n");
            sb.append("Content-Type: image/jpeg" + "\r\n");
            sb.append("\r\n");
            byte[] b = sb.toString().getBytes("UTF-8");


            URL url = new URL(u);
            File file = new File(path);
            int length = (int) file.length();

            Message message = Message.obtain();
            message.what = 201;
            message.obj = length;
            handler.sendMessage(message);

            HttpURLConnection http = (HttpURLConnection) url.openConnection();
//          添加响应头信息
            http.setRequestProperty("Content-Lenth", String.valueOf(b.length+file.length()));
            http.setRequestProperty("Content-Type", "multipart/form-data;boundary=7e324741816d4");
            http.setRequestMethod("POST");
            http.setReadTimeout(5000);
            http.setDoOutput(true);
            os = http.getOutputStream();
            
            fileInputStream = new FileInputStream(path);
            os.write(b);
            byte[] bytes = new byte[1024];
            int len = 0;
            int count = 0;

            while ((len=fileInputStream.read(bytes))!=-1) {
                count+=len;
                Thread.sleep(100);
                os.write(bytes,0,len);
                Message message2 = Message.obtain();
                message2.what = 200;
                message2.obj = count;
                handler.sendMessage(message2);
            }
            if (http.getResponseCode()==200){
                System.out.println("上传成功");
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (os!=null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fileInputStream!=null){
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
           

然后在主函数通过Handler判断并处理,代码如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    Button bt_download,bt_upload;
    ImageView imageView;
    ProgressBar bar1,bar2;
    @SuppressLint("HandlerLeak")
    Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 100:
                    bar1.setProgress((Integer) msg.obj);
                    if (bar1.getProgress()==bar1.getMax()){
                        Bitmap bitmap = BitmapFactory.decodeFile("/sdcard/a.jpg");
                        imageView.setImageBitmap(bitmap);
                        Toast.makeText(MainActivity.this, "下载成功!", Toast.LENGTH_SHORT).show();
                    }
                    break;
                case 101:
                    bar1.setMax((Integer) msg.obj);
                    break;

                case 200:
                    bar2.setProgress((Integer) msg.obj);
                    if (bar2.getProgress()==bar2.getMax()){
                        Toast.makeText(MainActivity.this, "上传成功!", Toast.LENGTH_SHORT).show();
                    }
                    break;
                case 201:
                    bar2.setMax((Integer)msg.obj);
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        bt_download = findViewById(R.id.bt_download);
        bt_upload = findViewById(R.id.bt_upload);
        bar1 = findViewById(R.id.pro1);
        bar2 = findViewById(R.id.pro2);
        imageView = findViewById(R.id.iv);

        bt_download.setOnClickListener(this);
        bt_upload.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.bt_download:
                download();
                break;
            case R.id.bt_upload:
                upload();
                break;
        }
    }

//  上传图片
    private void upload() {
        new UploadThread(handler,"http://169.254.61.144/hfs/","/sdcard/a.jpg","b.jpg").start();
    }

//  下载图片
    private void download() {
        new DownloadThread(handler,"http://169.254.61.144/hfs/a.jpg","/sdcard/a.jpg").start();
    }
}
           

响应码

常见的状态码

【1XX】表示【消息】

【2XX】表示【成功】

【3XX】表示【重定向】

【4XX】表示【请求错误】

【5XX】表示【服务器端错误】

Http协议Get与Post请求方式+响应码+断点续传+MVC架构

断点续传

public class DuandianActivity extends AppCompatActivity {
    Button button;
    ProgressBar bar;
    Handler handler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if(msg.what==101){//总大小
                bar.setMax((Integer) msg.obj);
            }else if(msg.what==102){//进度
                bar.setProgress((Integer) msg.obj);
            }else if(msg.what==103){
                Toast.makeText(DuandianActivity.this, "下载完毕", Toast.LENGTH_SHORT).show();
            }else if(msg.what==104){
                Toast.makeText(DuandianActivity.this, "文件已经存在", Toast.LENGTH_SHORT).show();
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_duandian);
        button=findViewById(R.id.bt_start);
        bar=findViewById(R.id.bar);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new DuanDianThread("http://uvideo.spriteapp.cn/video/2019/0512/56488d0a-7465-11e9-b91b-1866daeb0df1_wpd.mp4","/sdcard/aa.mp4").start();
            }
        });
    }

    class DuanDianThread extends Thread{
        private String url_str;
        private String filepath;

        public DuanDianThread(String url_str, String filepath) {
            this.url_str = url_str;
            this.filepath = filepath;
        }

        @Override
        public void run() {
            super.run();
            int end=0;
            int start=0;
            //TODO  1:第一次连接获取总大小:设置进度条最大值
            try {
                URL url = new URL(url_str);
                HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                if(urlConnection.getResponseCode()==200){
                    end= urlConnection.getContentLength();
                }
                Message obtain = Message.obtain();
                obtain.what=101;
                obtain.obj=end;
                handler.sendMessage(obtain);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }


            //TODO 2:第二从连接获得文件的IO流:start---end
            try {
                URL url = new URL(url_str);
                HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                //设置请求头信息  stat    end
                File file = new File(filepath);
                if(file.exists()){//文件是否存在
                    start= (int) file.length();//开始就是文件的总大小
                    if(start==end){

                        handler.sendEmptyMessage(104);
                    }
                }
                urlConnection.setRequestProperty("Range","bytes="+start+"-"+end);
                if(urlConnection.getResponseCode()==206){//返回响应码206
                    InputStream inputStream = urlConnection.getInputStream();
                    //随机访问流
                    RandomAccessFile  randomAccessFile=  new RandomAccessFile(filepath,"rw");//rw 可读可写
                    randomAccessFile.seek(start);
                    //边读边写
                    byte[] bytes=new byte[1024];
                    int len=0;
                    int count=start;//已经多少进度了
                    while((len=inputStream.read(bytes))!=-1){
                        randomAccessFile.write(bytes,0,len);
                        Thread.sleep(10);
                        count+=len;
                        Message obtain = Message.obtain();
                        obtain.what=102;
                        obtain.obj=count;
                        handler.sendMessage(obtain);
                        if(count==end){//下载完毕
                            handler.sendEmptyMessage(103);
                        }
                    }
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
           

MVC架构

MVC模式的结构分为三部分,实体层的Model,视图层的View,以及控制层的Controller。

  • V层(View):其中View层其实就是程序的UI界面,用于向用户展示数据以及接收用户的输入,XML布局可以视为V层,显示Model层的数据结果。
  • M层(model):适合做一些业务逻辑处理,比如数据库存取操作,网络操作,复杂的算法,耗时的任务等都在model层处理。
  • C层(Controller):控制器用于更新UI界面和数据实例.在Android中,Activity处理用户交互问题,因此可以认为Activity是控制器,Activity读取V视图层的数据(eg.读取当前EditText控件的数据),控制用户输入(eg.EditText控件数据的输入),并向Model发送数据请求(eg.发起网络请求等)。

继续阅读