欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android  斷點續(xù)傳的原理剖析與實例講解

 更新時間:2016年09月24日 10:39:45   投稿:lqh  
這篇文章主要介紹了Android 斷點續(xù)傳的原理剖析與實例講解的相關(guān)資料,需要的朋友可以參考下

 本文所要講的是Android斷點續(xù)傳的內(nèi)容,以實例的形式進行了詳細(xì)介紹。

       一、斷點續(xù)傳的原理

       其實斷點續(xù)傳的原理很簡單,就是在http的請求上和一般的下載有所不同而已。

       打個比方,瀏覽器請求服務(wù)器上的一個文時,所發(fā)出的請求如下:

       假設(shè)服務(wù)器域名為www.jizhuomi.com/android,文件名為down.zip。

get /down.zip http/1.1
accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-
excel, application/msword, application/vnd.ms-powerpoint, */*
accept-language: zh-cn
accept-encoding: gzip, deflate
user-agent: mozilla/4.0 (compatible; msie 5.01; windows nt 5.0)
connection: keep-alive

       服務(wù)器收到請求后,按要求尋找請求的文件,提取文件的信息,然后返回給瀏覽器,返回信息如下:

200
content-length=106786028
accept-ranges=bytes
date=mon, 30 apr 2001 12:56:11 gmt
etag=w/"02ca57e173c11:95b"
content-type=application/octet-stream
server=microsoft-iis/5.0
last-modified=mon, 30 apr 2001 12:56:11 gmt

       所謂斷點續(xù)傳,也就是要從文件已經(jīng)下載的地方開始繼續(xù)下載。所以在客戶端瀏覽器傳給web服務(wù)器的時候要多加一條信息--從哪里開始。

       下面是用自己編的一個“瀏覽器”來傳遞請求信息給web服務(wù)器,要求從2000070字節(jié)開始。

get /down.zip http/1.0
user-agent: netfox
range: bytes=2000070-
accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2

       仔細(xì)看一下就會發(fā)現(xiàn)多了一行 range: bytes=2000070-

       這一行的意思就是告訴服務(wù)器down.zip這個文件從2000070字節(jié)開始傳,前面的字節(jié)不用傳了。

       服務(wù)器收到這個請求以后,返回的信息如下:

206
content-length=106786028
content-range=bytes 2000070-106786027/106786028
date=mon, 30 apr 2001 12:55:20 gmt
etag=w/"02ca57e173c11:95b"
content-type=application/octet-stream
server=microsoft-iis/5.0
last-modified=mon, 30 apr 2001 12:55:20 gmt

       和前面服務(wù)器返回的信息比較一下,就會發(fā)現(xiàn)增加了一行:

content-range=bytes 2000070-106786027/106786028

       返回的代碼也改為206了,而不再是200了。

       知道了以上原理,就可以進行斷點續(xù)傳的編程了。

       二、java實現(xiàn)斷點續(xù)傳的關(guān)鍵幾點

       用什么方法實現(xiàn)提交range: bytes=2000070-?

       當(dāng)然用最原始的socket是肯定能完成的,不過那樣太費事了,其實java的net包中提供了這種功能。代碼如下:

Java代碼

url url = new url("http://www.jizhuomi.com/android/down.zip");  
httpurlconnection httpconnection = (httpurlconnection)url.openconnection();  
//設(shè)置user-agent  
httpconnection.setrequestproperty("user-agent","netfox");  
//設(shè)置斷點續(xù)傳的開始位置  
httpconnection.setrequestproperty("range","bytes=2000070");  
//獲得輸入流  
inputstream input = httpconnection.getinputstream(); 
    從輸入流中取出的字節(jié)流就是down.zip文件從2000070開始的字節(jié)流。

    大家看,其實斷點續(xù)傳用java實現(xiàn)起來還是很簡單的吧。

    接下來要做的事就是怎么保存獲得的流到文件中去了。

    保存文件采用的方法:我采用的是io包中的randaccessfile類。

    操作相當(dāng)簡單,假設(shè)從2000070處開始保存文件,代碼如下:

Java代碼
randomaccess osavedfile = new randomaccessfile("down.zip","rw");  
long npos = 2000070;  
//定位文件指針到npos位置  
osavedfile.seek(npos);  
byte[] b = new byte[1024];  
int nread;  
//從輸入流中讀入字節(jié)流,然后寫到文件中  
while((nread=input.read(b,0,1024)) > 0)  
{  
  osavedfile.write(b,0,nread);  
} 
    怎么樣,也很簡單吧。

    接下來要做的就是整合成一個完整的程序了。包括一系列的線程控制等等。

    三、斷點續(xù)傳內(nèi)核的實現(xiàn)

    主要用了6個類,包括一個測試類。

    sitefilefetch.java負(fù)責(zé)整個文件的抓取,控制內(nèi)部線程(filesplitterfetch類)。

    filesplitterfetch.java負(fù)責(zé)部分文件的抓取。

    fileaccess.java負(fù)責(zé)文件的存儲。

    siteinfobean.java要抓取的文件的信息,如文件保存的目錄,名字,抓取文件的url等。

    utility.java工具類,放一些簡單的方法。

    testmethod.java測試類。

    四、實例源碼

    下面是源程序:

Java代碼
/* 
**sitefilefetch.java 
*/ 
package netfox;  
import java.io.*;  
import java.net.*;  
  
public class sitefilefetch extends thread {  
  
siteinfobean siteinfobean = null; //文件信息bean  
long[] nstartpos; //開始位置  
long[] nendpos; //結(jié)束位置  
filesplitterfetch[] filesplitterfetch; //子線程對象  
long nfilelength; //文件長度  
boolean bfirst = true; //是否第一次取文件  
boolean bstop = false; //停止標(biāo)志  
file tmpfile; //文件下載的臨時信息  
dataoutputstream output; //輸出到文件的輸出流  
 
public sitefilefetch(siteinfobean bean) throws ioexception  
{  
siteinfobean = bean;  
//tmpfile = file.createtempfile ("zhong","1111",new file(bean.getsfilepath()));  
tmpfile = new file(bean.getsfilepath()+file.separator + bean.getsfilename()+".info");  
if(tmpfile.exists ())  
{  
bfirst = false;  
read_npos();  
}  
else 
{  
nstartpos = new long[bean.getnsplitter()];  
nendpos = new long[bean.getnsplitter()];  
}   
}  
  
public void run()  
{  
//獲得文件長度  
//分割文件  
//實例filesplitterfetch  
//啟動filesplitterfetch線程  
//等待子線程返回  
try{  
if(bfirst)  
{  
nfilelength = getfilesize();  
if(nfilelength == -1)  
{  
system.err.println("file length is not known!");  
}  
else if(nfilelength == -2)  
{  
system.err.println("file is not access!");  
}  
else 
{  
for(int i=0;i<nstartpos.length;i++)  
{  
nstartpos = (long)(i*(nfilelength/nstartpos.length));  
}  
for(int i=0;i<nendpos.length-1;i++)  
{  
nendpos = nstartpos[i+1];  
}  
nendpos[nendpos.length-1] = nfilelength;  
}  
}  
//啟動子線程  
filesplitterfetch = new filesplitterfetch[nstartpos.length];  
for(int i=0;i<nstartpos.length;i++)  
{  
filesplitterfetch = new filesplitterfetch(siteinfobean.getssiteurl(),  
siteinfobean.getsfilepath() + file.separator + siteinfobean.getsfilename(),  
nstartpos,nendpos,i);  
utility.log("thread " + i + " , nstartpos = " + nstartpos + ", nendpos = " + nendpos);  
filesplitterfetch.start();  
}  
// filesplitterfetch[npos.length-1] = new filesplitterfetch(siteinfobean.getssiteurl(),  
siteinfobean.getsfilepath() + file.separator + siteinfobean.getsfilename(),npos[npos.length-1],nfilelength,npos.length-1);  
// utility.log("thread " + (npos.length-1) + " , nstartpos = " + npos[npos.length-1] + ",  
nendpos = " + nfilelength);  
// filesplitterfetch[npos.length-1].start();  
 
//等待子線程結(jié)束  
//int count = 0;  
//是否結(jié)束while循環(huán)  
boolean breakwhile = false;  
  
while(!bstop)  
{  
write_npos();  
utility.sleep(500);  
breakwhile = true;  
  
for(int i=0;i<nstartpos.length;i++)  
{  
if(!filesplitterfetch.bdownover)  
{  
breakwhile = false;  
break;  
}  
}  
if(breakwhile)  
break;  
  
//count++;  
//if(count>4)  
// sitestop();  
}  
  
system.err.println("文件下載結(jié)束!");  
}  
catch(exception e){e.printstacktrace ();}  
}  
  
//獲得文件長度  
public long getfilesize()  
{  
int nfilelength = -1;  
try{  
url url = new url(siteinfobean.getssiteurl());  
httpurlconnection httpconnection = (httpurlconnection)url.openconnection ();  
httpconnection.setrequestproperty("user-agent","netfox");  
 
int responsecode=httpconnection.getresponsecode();  
if(responsecode>=400)  
{  
processerrorcode(responsecode);  
return -2; //-2 represent access is error  
}  
  
string sheader;  
  
for(int i=1;;i++)  
{  
//datainputstream in = new datainputstream(httpconnection.getinputstream ());  
//utility.log(in.readline());  
sheader=httpconnection.getheaderfieldkey(i);  
if(sheader!=null)  
{  
if(sheader.equals("content-length"))  
{  
nfilelength = integer.parseint(httpconnection.getheaderfield(sheader));  
break;  
}  
}  
else 
break;  
}  
}  
catch(ioexception e){e.printstacktrace ();}  
catch(exception e){e.printstacktrace ();}  
  
utility.log(nfilelength);  
  
return nfilelength;  
}  
  
//保存下載信息(文件指針位置)  
private void write_npos()  
{  
try{  
output = new dataoutputstream(new fileoutputstream(tmpfile));  
output.writeint(nstartpos.length);  
for(int i=0;i<nstartpos.length;i++)  
{  
// output.writelong(npos);  
output.writelong(filesplitterfetch.nstartpos);  
output.writelong(filesplitterfetch.nendpos);  
}  
output.close();  
}  
catch(ioexception e){e.printstacktrace ();}  
catch(exception e){e.printstacktrace ();}  
}  
  
//讀取保存的下載信息(文件指針位置)  
private void read_npos()  
{  
try{  
datainputstream input = new datainputstream(new fileinputstream(tmpfile));  
int ncount = input.readint();  
nstartpos = new long[ncount];  
nendpos = new long[ncount];  
for(int i=0;i<nstartpos.length;i++)  
{  
nstartpos = input.readlong();  
nendpos = input.readlong();  
}  
input.close();  
}  
catch(ioexception e){e.printstacktrace ();}  
catch(exception e){e.printstacktrace ();}  
}  
  
private void processerrorcode(int nerrorcode)  
{  
system.err.println("error code : " + nerrorcode);  
}  
  
//停止文件下載  
public void sitestop()  
{  
bstop = true;  
for(int i=0;i<nstartpos.length;i++)  
filesplitterfetch.splitterstop();  
}  
}  
/* 
**filesplitterfetch.java 
*/ 
package netfox;  
  
import java.io.*;  
import java.net.*;  
  
public class filesplitterfetch extends thread {  
  
string surl; //file url  
long nstartpos; //file snippet start position  
long nendpos; //file snippet end position  
int nthreadid; //threads id  
boolean bdownover = false; //downing is over  
boolean bstop = false; //stop identical  
fileaccessi fileaccessi = null; //file access interface  
  
public filesplitterfetch(string surl,string sname,long nstart,long nend,int id) throws ioexception  
{  
this.surl = surl;  
this.nstartpos = nstart;  
this.nendpos = nend;  
nthreadid = id;  
fileaccessi = new fileaccessi(sname,nstartpos);  
}  
  
public void run()  
{  
while(nstartpos < nendpos && !bstop)  
{   
try{  
url url = new url(surl);  
httpurlconnection httpconnection = (httpurlconnection)url.openconnection ();  
httpconnection.setrequestproperty("user-agent","netfox");  
string sproperty = "bytes="+nstartpos+"-";  
httpconnection.setrequestproperty("range",sproperty);  
utility.log(sproperty);  
  
inputstream input = httpconnection.getinputstream();  
//logresponsehead(httpconnection);  
  
byte[] b = new byte[1024];  
int nread;  
while((nread=input.read(b,0,1024)) > 0 && nstartpos < nendpos && !bstop)  
{  
nstartpos += fileaccessi.write(b,0,nread);  
//if(nthreadid == 1)  
// utility.log("nstartpos = " + nstartpos + ", nendpos = " + nendpos);  
}  
  
utility.log("thread " + nthreadid + " is over!");  
bdownover = true;  
//npos = fileaccessi.write (b,0,nread);  
}  
catch(exception e){e.printstacktrace ();}  
}  
}  
  
//打印回應(yīng)的頭信息  
public void logresponsehead(httpurlconnection con)  
{  
for(int i=1;;i++)  
{  
string header=con.getheaderfieldkey(i);  
if(header!=null)  
//responseheaders.put(header,httpconnection.getheaderfield(header));  
utility.log(header+" : "+con.getheaderfield(header));  
else 
break;  
}  
}  
  
public void splitterstop()  
{  
bstop = true;  
}   
}  
  
/* 
**fileaccess.java 
*/ 
package netfox;  
import java.io.*;  
  
public class fileaccessi implements serializable{  
  
randomaccessfile osavedfile;  
long npos;  
  
public fileaccessi() throws ioexception  
{  
this("",0);  
}  
  
public fileaccessi(string sname,long npos) throws ioexception  
{  
osavedfile = new randomaccessfile(sname,"rw");  
this.npos = npos;  
osavedfile.seek(npos);  
}  
  
public synchronized int write(byte[] b,int nstart,int nlen)  
{  
int n = -1;  
try{  
osavedfile.write(b,nstart,nlen);  
n = nlen;  
}  
catch(ioexception e)  
{  
e.printstacktrace ();  
}  
  
return n;  
}   
}  
  
/* 
**siteinfobean.java 
*/ 
package netfox;  
  
public class siteinfobean {  
  
private string ssiteurl; //sites url  
private string sfilepath; //saved files path  
private string sfilename; //saved files name  
private int nsplitter; //count of splited downloading file  
  
public siteinfobean()  
{  
//default value of nsplitter is 5  
this("","","",5);  
}  
  
public siteinfobean(string surl,string spath,string sname,int nspiltter)  
{  
ssiteurl= surl;  
sfilepath = spath;  
sfilename = sname;  
this.nsplitter = nspiltter;   
}  
  
public string getssiteurl()  
{  
return ssiteurl;  
}  
  
public void setssiteurl(string value)  
{  
ssiteurl = value;  
}  
  
public string getsfilepath()  
{  
return sfilepath;  
}  
  
public void setsfilepath(string value)  
{  
sfilepath = value;  
}  
  
public string getsfilename()  
{  
return sfilename;  
}  
  
public void setsfilename(string value)  
{  
sfilename = value;  
}  
  
public int getnsplitter()  
{  
return nsplitter;  
}  
 
public void setnsplitter(int ncount)  
{  
nsplitter = ncount;  
}  
}   
 
/* 
**utility.java 
*/ 
package netfox;  
  
public class utility {  
  
public utility()  
{  
}  
  
public static void sleep(int nsecond)  
{  
try{  
thread.sleep(nsecond);  
}  
catch(exception e)  
{  
e.printstacktrace ();  
}  
}  
  
public static void log(string smsg)  
{  
system.err.println(smsg);  
}  
  
public static void log(int smsg)  
{  
system.err.println(smsg);  
}  
}  
  
/* 
**testmethod.java 
*/ 
package netfox;  
  
public class testmethod {  
  
public testmethod()  
{ ///xx/weblogic60b2_win.exe  
try{  
siteinfobean bean = new siteinfobean("http://localhost/xx/weblogic60b2_win.exe","l:\\temp","weblogic60b2_win.exe",5);  
//siteinfobean bean = new siteinfobean("http://localhost:8080/down.zip","l:\\temp","weblogic60b2_win.exe",5);  
sitefilefetch filefetch = new sitefilefetch(bean);  
filefetch.start();  
}  
catch(exception e){e.printstacktrace ();}   
}  
  
public static void main(string[] args)  
{  
new testmethod();  
}  
}  

以上就是對Android 斷點續(xù)傳的資料整理,后續(xù)繼續(xù)補充相關(guān)資料,謝謝大家對本站的支持!

相關(guān)文章

  • Android ActionBar搜索功能用法詳解

    Android ActionBar搜索功能用法詳解

    這篇文章主要介紹了Android ActionBar搜索功能用法,較為詳細(xì)的分析了Android ActionBar搜索功能使用中的相關(guān)注意事項與操作技巧,需要的朋友可以參考下
    2016-07-07
  • Android監(jiān)聽鍵盤狀態(tài)獲取鍵盤高度的實現(xiàn)方法

    Android監(jiān)聽鍵盤狀態(tài)獲取鍵盤高度的實現(xiàn)方法

    這篇文章主要給大家介紹了關(guān)于Android監(jiān)聽鍵盤狀態(tài)獲取鍵盤高度的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • Android自定義View實現(xiàn)水波紋引導(dǎo)動畫

    Android自定義View實現(xiàn)水波紋引導(dǎo)動畫

    這篇文章主要為大家詳細(xì)介紹了Android自定義View實現(xiàn)水波紋動畫引導(dǎo),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Android?studio?利用共享存儲進行用戶的注冊和登錄驗證功能

    Android?studio?利用共享存儲進行用戶的注冊和登錄驗證功能

    這篇文章主要介紹了Android?studio?利用共享存儲進行用戶的注冊和登錄驗證功能,包括注冊頁面布局及登錄頁面功能,本文通過實例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2021-12-12
  • Android開發(fā)之Android studio的安裝與使用

    Android開發(fā)之Android studio的安裝與使用

    本文是此系列文章的第一篇,主要給大家講述的是Android studio的安裝與使用,十分的詳細(xì),有需要的小伙伴可以參考下
    2016-02-02
  • Androd 勇闖高階性能優(yōu)化之布局優(yōu)化篇

    Androd 勇闖高階性能優(yōu)化之布局優(yōu)化篇

    Android性能優(yōu)化方面也有很多文章了,這里就做一個總結(jié),從原理到方法,工具等做一個簡單的了解,從而可以慢慢地改變編碼風(fēng)格,從而提高性能
    2021-10-10
  • Android程序設(shè)計之AIDL實例詳解

    Android程序設(shè)計之AIDL實例詳解

    這篇文章主要介紹了Android程序設(shè)計的AIDL,以一個完整實例的形式較為詳細(xì)的講述了AIDL的原理及實現(xiàn)方法,需要的朋友可以參考下
    2014-09-09
  • Android sqlite cursor的遍歷實例詳解

    Android sqlite cursor的遍歷實例詳解

    在本篇內(nèi)容里小編給大家整理的是一篇關(guān)于Android sqlite cursor的遍歷的相關(guān)實例及知識點,需要的朋友們可以學(xué)習(xí)下。
    2021-06-06
  • 如何自己實現(xiàn)Android View Touch事件分發(fā)流程

    如何自己實現(xiàn)Android View Touch事件分發(fā)流程

    這篇文章主要介紹了如何自己實現(xiàn)Android View Touch事件分發(fā)流程,幫助大家更好的理解和學(xué)習(xí)使用Android,感興趣的朋友可以了解下
    2021-03-03
  • Android自定義流式布局的實現(xiàn)示例

    Android自定義流式布局的實現(xiàn)示例

    這篇文章主要介紹了Android自定義流式布局的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12

最新評論