天天看點

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.發起網絡請求等)。

繼續閱讀