常见两种网络请求方式
一、 HttpURLConnection
HttpURLConnection的setRequestProperty()方法,对我们要读取的字节部分进行控制,比如:
···
1.Range=0-100代表只读取前100个字节。
2.Range=100-500代表读取从第100个字节开始,读到第500个字节为止。
3.Range=100-则代表从第100个字节开始读取,一直读取到文件末尾结束。
···
断点续传过程
1、在暂停时记录一下已经读取到的位置,在重新开始的时候利用setRequestProperty()方法设置一下我们要读取的字节位置即可
2、RandomAccessFile来进行字节流的写入,RandomAccessFile有一个方法seek(long),允许我们指定要写入的位置
多线程断点续传实现原理相同,只是利用多个线程同时下载,每个线程指定要下载的字节部分,写入到文件的指定部分
二、 okhttp
1、调用请求获取文件长度
2、先判断文件是否找到,找到代表已经下载过,则获取其长度 判断长度是否大于文件长度 大于则创建新文件继续下载或者下载终止
3、设置请求头请求范围
//确定下载的范围,添加此头,则服务器就可以跳过已经下载好的部分
.addHeader("RANGE", "bytes=" + downloadLength + "-" + contentLength)
4、存储时候设置:RandomAccessFile这个类,但是如果不涉及到多个部分拼接的话是没必要的,直接使用输出流就好了,在输出流的构造方法上添加一个true的参数,代表是在原文件的后面添加数据即可
三 、 httpurlconnection 示例
class SingleDownloadTask{
private String filePath;
private int contentLength;
private int readLength;
private RandomAccessFile file=null;
private boolean isPause=false;
private URL url;
public boolean isDownloading() {
return isDownloading;
}
private boolean isDownloading=false;
private Handler mHandler=new Handler();
public SingleDownloadTask(String urlStr,String filePath) {
this.filePath=filePath;
readLength=0;
contentLength=0;
try {
url=new URL(urlStr);
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
//download from pos
public void download(){
new Thread(new Runnable() {
@Override
public void run() {
isDownloading=true;
HttpURLConnection conn=null;
InputStream is=null;
BufferedInputStream bis=null;
try {
file=new RandomAccessFile(filePath,"rw");
file.seek(readLength);
conn= (HttpURLConnection) url.openConnection();
if(readLength==0){
contentLength=conn.getContentLength();
}else{
conn.setRequestProperty("Range","bytes="+readLength+"-");
}
is=conn.getInputStream();
bis=new BufferedInputStream(is);
byte[] bytes=new byte[1024];
int len=0;
while (!isPause&&((len=bis.read(bytes,0,1024)))!=-1){
file.write(bytes,0,len);
readLength+=len;
mHandler.post(new Runnable() {
@Override
public void run() {
float rate=((float)readLength)/contentLength;
mProgressBar.setProgress((int) (100*rate));
mTextView.setText((int)(100*rate)+"%");
}
});
}
isDownloading=false;
if (readLength>=contentLength){
mHandler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "文件下载成功,保存在"+filePath
, Toast.LENGTH_SHORT).show();
mImageView.setImageBitmap(BitmapFactory.decodeFile(filePath));
}
});
}
file.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (bis!=null){
try {
bis.close();
if (is!=null){
is.close();
}
if (conn!=null){
conn.disconnect();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}).start();
}
public void start(){
isPause=false;
download();
}
public void pause(){
isPause=true;
}
}