Http协议+文件上传、下载、断点续传

Http协议

Http:超文本传输协议。

在这里插入图片描述

请求协议 request:

1、请求首行 (请求方式+网址+协议版本号)
2、请求头信息 (客户端告诉服务端的一些基本信息)
3、空行
4、请求体 (客户端向服务器提交的数据)

响应协议 response:

1、响应首行 (协议版本号+响应码+响应码描述) 200:成功 ,4xx:客户端错误,5xx:服务器错误,302:重定向 ,1xx:指示信息
2、响应头信息 服务器告诉客户端的一些信息 :Content-Length:2100846 返回数据大小
3、空行
4、响应体 服务端返回给客户端的数据

get和post的区别:

1、get没有请求体,post有请求体。
2、get向服务器要数据,post向服务器提交数据(登陆、注册、上传文件、头像)
3、get将请求参数暴露在url,不安全,post将请求参数放在请求体里面,安全。

文件下载

权限

	<uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
   

DownLoadThread:

package com.example.day1.thread;

import android.os.Handler;
import android.os.Message;

import com.example.day1.MainActivity;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;


public class DownLoadThread extends Thread{

    private String url; //网址
    private String path;//文件路径
    private Handler handler;

    public DownLoadThread(String url, String path, Handler handler) {
        this.url = url;
        this.path = path;
        this.handler = handler;
    }

    @Override
    public void run() {
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setReadTimeout(5000);
            connection.setConnectTimeout(5000);
            connection.connect();
            if (connection.getResponseCode()==200) {

                //获得总文件大小 - 发送
                int max = connection.getContentLength();
                Message message = new Message();
                message.what= MainActivity.SEEKBAR_MAX;
                message.obj=max;
                handler.sendMessage(message);

                InputStream is = connection.getInputStream();

                FileOutputStream fos = new FileOutputStream(path);
                byte[] bys = new byte[1024];
                int len=0;
                int count=0;
                while ((len=is.read(bys))!=-1) {
                    fos.write(bys,0,len);
                    count+=len;

                    //发送读取长度
                    Message message1 = new Message();
                    message1.what= MainActivity.SEEKBAR_COUNT;
                    message1.obj=count;
                    handler.sendMessage(message1);

                    if (count==len) {
                    //下载完成
                        Message message2 = new Message();
                        message2.what= MainActivity.SEEKBAR_FINISH;
                        handler.sendMessage(message2);
                    }



                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

文件上传

需要设置请求头、请求体信息。

1.设置请求头信息:

Content-Length:请求体的总长度
Content-Type:multipart/form-data; boundary=7e324741816d4

2.请求体:2部分

第一部分:要有换行
-----------------------------7e324741816d4
Content-Disposition: form-data; name=“file”; filename=“上传到服务器的名字”
Content-Type: media/mp4或者media/mp3或者image/mp3或者image/png
空行

UpLoadThread:

package com.example.day1.thread;

import android.os.Handler;
import android.util.Log;
import android.widget.Toast;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;


public class UpLoadThread extends Thread{


    String url; // 网址
    String path; //文件路径
    String filename; //文件名
    private Handler handler;

    public UpLoadThread(String url, String path, String filename, Handler handler) {
        this.url = url;
        this.path = path;
        this.filename = filename;
        this.handler = handler;
    }

    @Override
    public void run() {
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();

//
            //TODO 第一部分
//            -----------------------------7e324741816d4
//            Content-Disposition: form-data; name="file"; filename="上传到服务器的名字"
//            Content-Type: media/mp4或者media/mp3或者image/mp3或者image/png
            StringBuffer sb = new StringBuffer();
            sb.append("-----------------------------7e324741816d4"+"\r\n");
            sb.append("Content-Disposition: form-data; name=\"file\"; filename=\""+filename+"\""+"\r\n");
            sb.append("Content-Type: image/jpg"+"\r\n");
            sb.append("\r\n");

            byte[] bytes = sb.toString().getBytes();

            //TODO 请求头信息
//            Content-Length:请求体的总长度
//            Content-Type:multipart/form-data; boundary=7e324741816d4
            Log.d("ytx", "run: "+(bytes.length+new File(path).length()));
            connection.setRequestProperty("Content-Length",bytes.length+new File(path).length()+"");
            connection.setRequestProperty("Content-Type","multipart/form-data; boundary=7e324741816d4");

            //TODO POST请求
            connection.setRequestMethod("POST");
            connection.setDoOutput(true);
            OutputStream os = connection.getOutputStream();
            os.write(bytes);

            //边读边发
            FileInputStream fis = new FileInputStream(path);
            byte[] bys = new byte[1024];
            int len=0;
            int count=0;
            while ((len=fis.read(bys))!=-1) {
                os.write(bys,0,len);
                count+=len;
            }
            Log.d("ytx", "run: "+(count+bytes.length));

            //发起连接
            connection.connect();
            if (connection.getResponseCode()==200) {
                Log.i("TAG", "上传成功 ");
            }


        } catch (Exception e) {
            e.printStackTrace();
        }


    }
}

MainActivity:

                new UpLoadThread("http://169.254.113.244/1705hfs/","/sdcard/Pictures/QQ图片20181212140907.jpg","yu.jpg",handler).start();

断点续传

设置请求头:

Range:bytes=起始位置-终点位置。

随机访问流:

RandomAccessFile(文件路径,“rw”)
seek(start) 从指定位置开始写

DuanDianThread:

package com.example.day1.thread;

import android.os.Handler;
import android.os.Message;

import com.example.day1.MainActivity;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

public class DuanDianThread extends Thread{

    String url;
    String path;
    private Handler handler;

    public DuanDianThread(String url, String path, Handler handler) {
        this.url = url;
        this.path = path;
        this.handler = handler;
    }

    @Override
    public void run() {

        int start =0;
        int end=0;

        //先获取总长度
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setReadTimeout(5000);
            connection.setConnectTimeout(5000);
            connection.connect();
            if (connection.getResponseCode()==200) {

                end=connection.getContentLength();
            }
            //将总长度发给主线程设置给进度条
            Message obtain = Message.obtain();
            obtain.what= MainActivity.SEEKBAR_MAX;
            obtain.obj=end;
            handler.sendMessage(obtain);


            //第二次请求
            HttpURLConnection c = (HttpURLConnection) new URL(url).openConnection();

            File file = new File(path);
            if (file.exists()) {
                //该文件已存在,断点续传
                start= (int) file.length();
            }
            c.setRequestProperty("Range","bytes="+start+"-"+end);

            if (c.getResponseCode()==206) {
                InputStream is = c.getInputStream();

                //随机访问流
                RandomAccessFile randomAccessFile = new RandomAccessFile(path, "rw");
                randomAccessFile.seek(start);

                byte[] bys = new byte[1024];
                int len=0;
                int count=start;
                while ((len=is.read(bys))!=-1) {
                    randomAccessFile.write(bys,0,len);

                    count+=len;//实时更新
                    //发送消息给主线程更新进度条
                    Message obtain1 = Message.obtain();
                    obtain1.what=MainActivity.SEEKBAR_COUNT;
                    obtain1.obj=count;
                    handler.sendMessage(obtain1);

                    //判断是否下载完毕
                    if (start==end) {
                        handler.sendEmptyMessage(MainActivity.SEEKBAR_FINISH);
                    }

                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

handler进度条更新

 Handler handler=new Handler(){
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if (msg.what==SEEKBAR_MAX) {
                Log.i("TAG", "设置最大长度 "+msg.obj);
                seekBar2.setMax((Integer) msg.obj);
            } else if (msg.what==SEEKBAR_COUNT) {
                Log.i("TAG", "设置读取"+msg.obj);
                seekBar2.setProgress((Integer) msg.obj);
            }else if (msg.what==SEEKBAR_FINISH) {
                Log.i("TAG", "设置读取"+msg.obj);
                Toast.makeText(MainActivity.this, "下载完毕", Toast.LENGTH_SHORT).show();

            }
        }
    };

网络七层

应用层:应用程序,用户看的见 http协议
表示层:将人看的懂的转成计算机看的懂
会话层:发起一个连接
传输层:规定传输协议和端口号 tcp协议 udp协议
网络层:规定网络ip ip协议
数据链路层:
物理层:光缆、网线

7种请求方式:

1、OPTIONS
返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送‘*’的请求来测试服务器的功能性
2、HEAD
向服务器索与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以再不必传输整个响应内容的情况下,就可以获取包含在响应小消息头中的元信息。
3、GET
向特定的资源发出请求。它本质就是发送一个请求来取得服务器上的某一资源。资源通过一组HTTP头和呈现数据(如HTML文本,或者图片或者视频等)返回给客户端。
4、POST
向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。
5、PUT
向指定资源位置上传其最新内容
6、DELETE
请求服务器删除Request-URL所标识的资源
7、TRACE
回显服务器收到的请求,主要用于测试或诊断
8、CONNECT
HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。

常见的响应码

1xx:指示信息
200:成功 ,
302:重定向 ,
4xx:客户端错误,
5xx:服务器错误,

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值