('0.使用多线程下载会提升文件下载的速度,那么多线程下载文件的过程是:(1)首先获得下载文件的长度,然后设置本地文件的长度HttpURLConnection.getContentLength();RandomAccessFilefile=newRandomAccessFile("QQWubiSetup.exe","rwd");file.setLength(filesize);//设置本地文件的长度(2)根据文件长度和线程数计算每条线程下载的数据长度和下载位置。如:文件的长度为6M,线程数为3,那么,每条线程下载的数据长度为2M,每条线程开始下载的位置如下图所示。例如10M大小,使用3个线程来下载,线程下载的数据长度(10%3==0?10/3:10/3+1),第1,2个线程下载长度是4M,第三个线程下载长度为2M下载开始位置:线程id每条线程下载的数据长度=?下载结束位置:(线程id+1)每条线程下载的数据长度-1=?(3)使用Http的Range头字段指定每条线程从文件的什么位置开始下载,下载到什么位置为止,如:指定从文件的2M位置开始下载,下载到位置(4M-1byte)为止代码如下:HttpURLConnection.setRequestProperty("Range","bytes=2097152-4194303");(4)保存文件,使用RandomAccessFile类指定每条线程从本地文件的什么位置开始写入数据。RandomAccessFilethreadfile=newRandomAccessFile("QQWubiSetup.exe","rwd");threadfile.seek(2097152);//从文件的什么位置开始写入数据1.多线程下载的核心代码示例Java代码1.publicclassMulThreadDownload2.{3./4.多线程下载5.6.7.publicstaticvoidmain(String[]args)8.{9.Stringpath="http://net.hoo.com/QQWubiSetup.exe";10.try11.{12.newMulThreadDownload().download(path,3);13.}14.catch(Exceptione)15.{16.e.printStackTrace();17.}18.}19./20.从路径中获取文件名称21.22.23.24.publicstaticStringgetFilename(Stringpath)25.{26.returnpath.substring(path.lastIndexOf(\'/\')+1);27.}28./29.下载文件30.31.32.33.publicvoiddownload(Stringpath,intthreadsize)throwsException34.{35.URLurl=newURL(path);36.HttpURLConnectionconn=(HttpURLConnection)url.openConnection();37.conn.setRequestMethod("GET");38.conn.setConnectTimeout(51000);39.//获取要下载的文件的长度40.intfilelength=conn.getContentLength();41.//从路径中获取文件名称42.Stringfilename=getFilename(path);43.FilesaveFile=newFile(filename);44.RandomAccessFileaccessFile=newRandomAccessFile(saveFile,"rwd");45.//设置本地文件的长度和下载文件相同46.accessFile.setLength(filelength);47.accessFile.close();48.//计算每条线程下载的数据长度49.intblock=filelength%threadsize==0?filelength/threadsize:filelength/threadsize+1;50.for(intthreadid=0;threadiddata=newConcurrentHashMap();33.//每条线程下载的长度34.privateintblock;35.//下载路径36.privateStringdownloadUrl;37.//获取线程数38.publicintgetThreadSize()39.{40.returnthreads.length;41.}42./43.获取文件大小44.45.46.publicintgetFileSize()47.{48.returnfileSize;49.}50./51.累计已下载大小52.53.54.protectedsynchronizedvoidappend(intsize)55.{56.downloadSize+=size;57.}58./59.更新指定线程最后下载的位置60.61.62.63.protectedsynchronizedvoidupdate(intthreadId,intpos)64.{65.this.data.put(threadId,pos);66.this.fileService.update(this.downloadUrl,this.data);67.}68./69.文件下载构造器70.71.72.73.74.publicFileDownloader(Contextcontext,StringdownloadUrl,FilefileSaveDir,intthreadNum)75.{76.try77.{78.this.context=context;79.this.downloadUrl=downloadUrl;80.fileService=newFileService(this.context);81.URLurl=newURL(this.downloadUrl);82.if(!fileSaveDir.exists())fileSaveDir.mkdirs();83.this.threads=newDownloadThread[threadNum];84.HttpURLConnectionconn=(HttpURLConnection)url.openConnection();85.conn.setConnectTimeout(51000);86.conn.setRequestMethod("GET");87.conn.setRequestProperty("Accept","image/gif,image/jpeg,image/pjpeg,image/pjpeg,application/x-shockwave-flash,application/xaml+xml,application/vnd.ms-xpsdocument,application/x-ms-xbap,application/x-ms-application,application/vnd.ms-excel,application/vnd.ms-powerpoint,application/msword,");88.conn.setRequestProperty("Accept-Language","zh-CN");89.conn.setRequestProperty("Referer",downloadUrl);90.conn.setRequestProperty("Charset","UTF-8");91.conn.setRequestProperty("User-Agent","Mozilla/4.0(compatible;MSIE8.0;WindowsNT5.2;Trident/4.0;.NETCLR1.1.4322;.NETCLR2.0.50727;.NETCLR3.0.04506.30;.NETCLR3.0.4506.2152;.NETCLR3.5.30729)");92.conn.setRequestProperty("Connection","Keep-Alive");93.conn.connect();94.printResponseHeader(conn);95.if(conn.getResponseCode()==200)96.{97.//根据响应获取文件大小98.this.fileSize=conn.getContentLength();99.if(this.fileSize<=0)thrownewRuntimeException("Unkownfilesize");100.//获取文件名称101.Stringfilename=getFileName(conn);102.//构建保存文件103.this.saveFile=newFile(fileSaveDir,filename);104.//获取下载记录105.Maplogdata=fileService.getData(downloadUrl);106.//如果存在下载记录107.if(logdata.size()>0)108.{109.//把各条线程已经下载的数据长度放入data中110.for(Map.Entryentry:logdata.entrySet())111.data.put(entry.getKey(),entry.getValue());112.}113.//下面计算所有线程已经下载的数据长度114.if(this.data.size()==this.threads.length)115.{116.for(inti=0;i0)randOut.setLength(this.fileSize);168.randOut.close();169.URLurl=newURL(this.downloadUrl);170.if(this.data.size()!=this.threads.length)171.{172.this.data.clear();173.for(inti=0;igetHttpResponseHeader(HttpURLConnectionhttp){240.Mapheader=newLinkedHashMap();241.for(inti=0;;i++){242.Stringmine=http.getHeaderField(i);243.if(mine==null)break;244.header.put(http.getHeaderFieldKey(i),mine);245.}246.returnheader;247.}248./249.打印Http头字段250.251.252.publicstaticvoidprintResponseHeader(HttpURLConnectionhttp)253.{254.Mapheader=getHttpResponseHeader(http);255.for(Map.Entryentry:header.entrySet())256.{257.Stringkey=entry.getKey()!=null?entry.getKey()+":":"";258.print(key+entry.getValue());259.}260.}261.privatestaticvoidprint(Stringmsg)262.{263.Log.i(TAG,msg);264.}265.}Java代码1.publicinterfaceDownloadProgressListener2.{3.publicvoidonDownloadSize(intsize);4.}(2)文件操作,断点数据库存储Java代码1.publicclassDBOpenHelperextendsSQLiteOpenHelper2.{3.privatestaticfinalStringDBNAME="itcast.db";4.privatestaticfinalintVERSION=1;5.6.publicDBOpenHelper(Contextcontext)7.{8.super(context,DBNAME,null,VERSION);/文件下载器,使用这个类的方法如下示例:FileDownloaderloader=newFileDownloader(contenewFile("D:\\\\androloader.getFileSize();//得到文件总大小try{loader.download(newDownloapublicvoidonDownlprint("已经}});}catch(Exceptione){e.printStackTrace();}publicclassFileDownloaderpublicinterfaceDownloadProgressListener{publicvoidonDownloadSize(intsize);}9.}10.11.@Override12.publicvoidonCreate(SQLiteDatabasedb)13.{14.db.execSQL("CREATETABLEIFNOTEXISTSfiledownlog(idintegerprimarykeyautoincrement,downpathvarchar(100),threadidINTEGER,downlengthINTEGER)");15.}16.@Override17.publicvoidonUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion)18.{19.db.execSQL("DROPTABLEIFEXISTSfiledownlog");20.onCreate(db);21.}22.}Java代码1./2.文件下载业务bean3.4.publicclassFileService5.{6.privateDBOpenHelperopenHelper;7.publicFileService(Contextcontext)8.{9.openHelper=newDBOpenHelper(context);publicclassDBOpenHelperextendsSQLiteOpenHelper{privatestaticfinalStringDBNAME="itcasprivatestaticfinalintVERSION=1;publicDBOpenHelper(Contextcontext){super(context,DBNAME,null,VERSIO}@OverridepublicvoidonCreate(SQLiteDatabasedb){db.execSQL("CREATETABLEIFNOTEXI}@OverridepublicvoidonUpgrade(SQLiteDatabasedb,in{10.}11./12.获取每条线程已经下载的文件长度13.14.15.16.publicMapgetData(Stringpath)17.{18.SQLiteDatabasedb=openHelper.getReadableDatabase();19.Cursorcursor=db.rawQuery("selectthreadid,downlengthfromfiledownlogwheredownpath=?",newString[]{path});20.Mapdata=newHashMap();21.while(cursor.moveToNext())22.{23.data.put(cursor.getInt(0),cursor.getInt(1));24.}25.cursor.close();26.db.close();27.returndata;28.}29./30.保存每条线程已经下载的文件长度31.32.33.34.publicvoidsave(Stringpath,Mapmap)35.{//intthreadid,intposition36.SQLiteDatabasedb=openHelper.getWritableDatabase();37.db.beginTransaction();38.try39.{40.for(Map.Entryentry:map.entrySet())41.{42.db.execSQL("insertintofiledownlog(downpath,threadid,downlength)values(?,?,?)",43.newObject[]{path,entry.getKey(),entry.getValue()});44.}45.db.setTransactionSuccessful();46.}47.finally48.{49.db.endTransaction();50.}51.db.close();52.}53./54.实时更新每条线程已经下载的文件长度55.56.57.58.publicvoidupdate(Stringpath,Mapmap)59.{60.SQLiteDatabasedb=openHelper.getWritableDatabase();61.db.beginTransaction();62.try{63.for(Map.Entryentry:map.entrySet()){64.db.execSQL("updatefiledownlogsetdownlength=?wheredownpath=?andthreadid=?",65.newObject[]{entry.getValue(),path,entry.getKey()});66.}67.db.setTransactionSuccessful();68.}finally{69.db.endTransaction();70.}71.db.close();72.}73./74.当文件下载完成后,删除对应的下载记录75.76.77.publicvoiddelete(Stringpath)78.{79.SQLiteDatabasedb=openHelper.getWritableDatabase();80.db.execSQL("deletefromfiledownlogwheredownpath=?",newObject[]{path});81.db.close();82.}83.}',)