android基础之二——网络编程(二)

01_post方式提交数据的中文乱码解决

解决办法:保证客户端和服务器端使用的字符集编码一致。

    Tomcat默认的字符集编码是iso-8859-1,默认是iso-8859-1进行转码
    String username = request.getParameter("username"); 
    String password = request.getParameter("password");

    Tomcat默认的字符集编码是iso-8859-1,默认是iso-8859-1进行转码,当它发现使用iso-8859-1不能编码中文的时候,会使用操作系统使用的本地码表(字符集编码)进行编码,所以我们需要自己编码response.getOutputStream().write("登陆成功".getBytes("UTF-8"));

02_get提交数据乱码的解决

04_使用HttpClient向服务器端提交数据

HttpClient : apache子项目

HttpClient 轻量级的浏览器

步骤:

   1、创建一个浏览器
   2、输入一个网址
   3、按回车

模版代码GET方式:

                    //1、创建一个浏览器
                     HttpClient client = new DefaultHttpClient();
                     //2、输入一个网址
                     HttpGet httpGet = new HttpGet(path);
                    //3、按回车
                     HttpResponse response = client.execute(httpGet);


                    //4、获取服务器端返回的响应数据,判断响应码,200ok,404找不到资源、503服务器内部错误,然后获取输入流;
                    int code = response.getStatusLine().getStatusCode();
                    if(code == 200){
                        //获取返回的二进制数据流
                        InputStream is = response.getEntity().getContent();

模版代码POST方式:

                    //1、创建一个浏览器

                     HttpClient client = new DefaultHttpClient();
                    // 2、输入一个网址
                     HttpPost httpPost = new HttpPost(path);

                     //封装提交的数据
                     //类似map的数据结构
                     BasicNameValuePair username = new BasicNameValuePair("username", qq);

                     BasicNameValuePair password = new BasicNameValuePair("password", pwd);

                     List<BasicNameValuePair> list = new ArrayList<BasicNameValuePair>();
                     list.add(username);
                     list.add(password);
                     //默认是使用iso-8859-1转码的
                     UrlEncodedFormEntity entity = new UrlEncodedFormEntity(list,"UTF-8");

                    httpPost.setEntity(entity);
                    //3、按回车
                     HttpResponse response = client.execute(httpPost);

                    //4、获取服务器端返回的响应数据,判断响应码,200ok,404找不到资源、503服务器内部错误,然后获取输入流;
                    int code = response.getStatusLine().getStatusCode();
                    if(code == 200){
                    //获取返回的二进制数据流
                    InputStream is = response.getEntity().getContent();

05使用开源项目Asynchttpclient的GETPOST访问网络

  • 使用GET方式发送请求:

    public void login(View view){
        String qq = et_qq.getText().toString().trim();
        String pwd = et_pwd.getText().toString().trim();
        try {
            path = "http://192.168.13.41:8080/web/servlet/LoginServlet?username="+URLEncoder.encode(qq,"UTF-8")+"&password="+URLEncoder.encode(pwd, "UTF-8");
    
            AsyncHttpClient client = new AsyncHttpClient();
    
            client.get(path, new AsyncHttpResponseHandler() {
    
                /**
                 * 请求成功,服务器端正常响应调用这个方法
                 * statusCode 响应码
                 * headers 响应头信息
                 * 
                 * responseBody 服务器端返回的数据实体的字节数组
                 */
                @Override
                public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                    Toast.makeText(MainActivity.this, new String(responseBody), 0).show();
               }
    
                /**
                 * 请求成功,服务器端正常响应调用这个方法
                 * statusCode 响应码
                 * headers 响应头信息
                 * responseBody 服务器端返回的数据实体的字节数组
                 * error 服务器端抛出来的异常信息 
                 */
                @Override
                public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
                    Toast.makeText(MainActivity.this, "处理失败;"+new String(responseBody), 0).show();
                }
            });
    
    
        } catch (Exception e) {
            e.printStackTrace();
        }
    

    }

  • 使用POST方式发送请求:

    path = "http://192.168.13.41:8080/web/servlet/LoginServlet";
                //1、创建一个浏览器
                AsyncHttpClient client = new AsyncHttpClient();
    
            //2、设置参数
            RequestParams params = new RequestParams();
    
            params.put("username", qq);
            params.put("password", pwd);
    
            //3、发送请求
            client.post(path, params, new AsyncHttpResponseHandler() {
    
                /**
                 * 请求成功,服务器端正常响应调用这个方法
                 * statusCode 响应码
                 * headers 响应头信息
                 * 
                 * responseBody 服务器端返回的数据实体的字节数组
                 */
                @Override
                public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
                    Toast.makeText(MainActivity.this, new String(responseBody), 0).show();
               }
    
                /**
                 * 请求成功,服务器端正常响应调用这个方法
                 * statusCode 响应码
                 * headers 响应头信息
                 * responseBody 服务器端返回的数据实体的字节数组
                 * error 服务器端抛出来的异常信息 
                 */
                @Override
                public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
                    Toast.makeText(MainActivity.this, "处理失败;"+new String(responseBody), 0).show();
                }
            });
    

06_上传文件

代码:

        AsyncHttpClient client = new AsyncHttpClient();

        RequestParams params = new RequestParams();

        File file = new File(path);
        //创建一个文件,作为一个参数提交给服务器端
        params.put("file", file);

        client.post("http://192.168.13.41:8080/web/servlet/UploadServlet", params, new AsyncHttpResponseHandler() {

            @Override
            public void onSuccess(int arg0, Header[] arg1, byte[] arg2) {
                Toast.makeText(MainActivity.this,   new String(arg2), 0).show();

            }

            @Override
            public void onFailure(int arg0, Header[] arg1, byte[] arg2, Throwable arg3) {
                Toast.makeText(MainActivity.this,   "处理失败;", 0).show();
                arg3.printStackTrace();

            }
        });

07_多线程加速下载的原理

08_多线程下载的原理

需要解决问题:
1、在客户端创建一个与服务器端一样大小的空文件:content-length;RandomAccessFile
2、根据线程的个数等分文件,计算出每个线程下载的数据块大小:length/threadcount=blocksize
3、计算每个子线程下载数据的开始位置和结束位置:
   开始位置:threadid*blocksize 结束位置:(threadid+1)*blocksize-1
   最后一个子线程的开始为位置:threadid*blocksize ,结束位置:length-1
4、确定每个子线程从什么开始写数据:seek()
5、创建子线程,开始下载数据;
6、确定每个子线程都下载完毕,以此来确定每个文件下载完成;

09_javase多线程下载的逻辑

代码:MultiThreadDownLoader.java

package com.itheima;

import java.io.File;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

public class MultiThreadDownLoader {
private static int threadCount = 3;

public static void main(String[] args) {

    try {
        String path = "http://192.168.13.41:8080/sogou.exe";

        URL url = new URL(path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(3000);

        int code = conn.getResponseCode();
        if(code == 200){
        //1、在客户端创建一个与服务器端一样大小的空文件:content-length;RandomAccessFile
        int length = conn.getContentLength();
        File file = new File("temp.exe");
        RandomAccessFile raf = new RandomAccessFile(file, "rw");
        raf.setLength(length);
//           2、根据线程的个数等分文件,计算出每个线程下载的数据块大小:length/threadcount=blocksize
        int blockSize = length/threadCount;

//          3、计算每个子线程下载数据的开始位置和结束位置:
//             开始位置:threadid*blocksize 结束位置:(threadid+1)*blocksize-1
//             最后一个子线程的开始为位置:threadid*blocksize ,结束位置:length-1
        for(int threadId=0; threadId<threadCount; threadId++){
            //开始位置
            int startIndex = threadId * blockSize;
            //结束位置
            int endIndex = (threadId+1)*blockSize-1;
            //最后一个线程下载的结束位置
            if(threadId==threadCount-1){
                endIndex =  length-1;
            }

//              4、确定每个子线程从什么开始写数据:seek()
//              5、创建子线程,开始下载数据;
           new ChildThreadDownLoader(startIndex,endIndex,threadId,path).start();
        }


//                    
        }

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

}

子线程下载:ChildThreadDownLoader.java

package com.itheima;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;

public class ChildThreadDownLoader extends Thread {

private static int runningThreadCount = 3;
private int startIndex;
private int endIndex;
private int threadId;
private String path;

public ChildThreadDownLoader(int startIndex, int endIndex, int threadId,
        String path) {

    this.startIndex = startIndex;
    this.endIndex = endIndex;
    this.threadId = threadId;
    this.path = path;
}


  @Override
public void run() {
    try {
        URL url = new URL(path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(3000);
        //设置请求数据的数范围 bytes=0-3
        conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);

        int code = conn.getResponseCode();
        //成功返回部分数据code=206 200表示返回全部数据
        if(code == 206){
        //1、在客户端创建一个与服务器端一样大小的空文件:content-length;RandomAccessFile
        InputStream is = conn.getInputStream();
        File file = new File("temp.exe");
        RandomAccessFile raf = new RandomAccessFile(file, "rwd");

        System.out.println("线程"+threadId+"开始下载:"+startIndex+","+endIndex);
//          4、确定每个子线程从什么开始写数据:seek()
        raf.seek(startIndex);
        //开始下载数据
        byte[] buffer = new byte[1024*20];
        int len = -1;
        while((len = is.read(buffer)) != -1){
            raf.write(buffer, 0, len);
        }

        is.close();
        raf.close();

        System.out.println("线程"+threadId+"下载完成..............");

        //6、确定每个子线程都下载完毕,以此来确定每个文件下载完成;
        synchronized (ChildThreadDownLoader.class) {
            runningThreadCount--;
            if(runningThreadCount == 0){
                System.out.println("文件下载完毕........................");
            }
        }

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

}

}

10_javase多线程断点下载

1、知道每个子线程上次下载到了什么位置

实时的记录每个子线程下载到的位置,写到一个文件里;

2、获取没格子线程上次下载到的位置,下次下载时接着上一次下载:

读取文件,得到上次下载到的位置,接着下载;

代码:

package com.itheima;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;

public class ChildThreadDownLoader extends Thread {

private static int runningThreadCount = 3;
private int startIndex;
private int endIndex;
private int threadId;
private String path;

public ChildThreadDownLoader(int startIndex, int endIndex, int threadId,
        String path) {

    this.startIndex = startIndex;
    this.endIndex = endIndex;
    this.threadId = threadId;
    this.path = path;
}


  @Override
public void run() {
    try {
        URL url = new URL(path);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setConnectTimeout(3000);
        //2、获取没格子线程上次下载到的位置,下次下载时接着上一次下载:读取文件,得到上次下载到的位置,接着下载;
        File info = new File(threadId+".txt");
        if(info.exists() && info.length()>0){
            FileReader fr = new FileReader(info);
            BufferedReader br = new BufferedReader(fr);
            String lastDownPosition = br.readLine();
            startIndex = Integer.valueOf(lastDownPosition);
        }
        //设置请求数据的数范围 bytes=0-3
        conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);

        int code = conn.getResponseCode();
        //成功返回部分数据code=206 200表示返回全部数据
        if(code == 206){
        //1、在客户端创建一个与服务器端一样大小的空文件:content-length;RandomAccessFile
        InputStream is = conn.getInputStream();
        File file = new File("temp.exe");
        RandomAccessFile raf = new RandomAccessFile(file, "rwd");




        System.out.println("线程"+threadId+"开始下载:"+startIndex+","+endIndex);
//          4、确定每个子线程从什么开始写数据:seek()
        raf.seek(startIndex);
        //开始下载数据
        byte[] buffer = new byte[1024*20];
        int len = -1;
        int total=0;
        while((len = is.read(buffer)) != -1){
            raf.write(buffer, 0, len);
            //把当前下载到的位置记录到文件里
            total = total + len;
            int currentPosition = startIndex + total;
            RandomAccessFile f = new RandomAccessFile(threadId+".txt","rwd");
            f.write((currentPosition+"").getBytes());
            f.close();
        }
        is.close();
        raf.close();

        System.out.println("线程"+threadId+"下载完成..............");

        //6、确定每个子线程都下载完毕,以此来确定每个文件下载完成;
        synchronized (ChildThreadDownLoader.class) {
            runningThreadCount--;
            if(runningThreadCount == 0){
                System.out.println("文件下载完毕........................");
            }
        }

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

}

}

11_多线程下载的Android移植

12_开目实现多线程下载

  • 示例代码:

    HttpUtils http = new HttpUtils();
        HttpHandler handler = http.download(path,
    
        Environment.getExternalStorageDirectory()+"/sogou.exe",
            true, // 如果目标文件存在,接着未完成的部分继续下载。服务器不支持RANGE时将从新下载。
            true, // 如果从请求返回信息中获取到文件名,下载完成后自动重命名。
            new RequestCallBack<File>() {
    
                @Override
                public void onStart() {
                    tv_start.setText("conn...");
                }
    
                @Override
                public void onLoading(long total, long current, boolean isUploading) {
                    tv_progress.setText(current + "/" + total);
                }
    
                @Override
                public void onSuccess(ResponseInfo<File> responseInfo) {
                    Toast.makeText(MainActivity.this, "下载完成,文件在"+responseInfo.result.getPath(), 0).show();
                }
    
    
                @Override
                public void onFailure(HttpException error, String msg) {
                    Toast.makeText(MainActivity.this, "下载失败", 0).show();
                    error.printStackTrace();
                }
        });
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值