Android-multi-thread download process analysis

Source: Internet
Author: User

Android-multi-thread download process analysis

The process of multi-threaded File Download is as follows:

(1) first obtain the length of the downloaded file, and then set the length of the local file.

HttpURLConnection. getContentLength (); // obtain the length of the downloaded object

RandomAccessFile file = new RandomAccessFile ("QQSetup.exe", "rwd ");

File. setLength (filesize); // you can specify the length of a local file.

 

(2) Calculate the length and location of Data downloaded by each thread Based on the file length and thread count.

For example, if the file length is 6 MB and the number of threads is 3, the data downloaded by each thread is 2 MB, as shown in.

For example, the size is 10 MB and three threads are used for download,

The Data Length downloaded by the thread (10% 3 = 0? 10/3: 10/3 + 1). The download length of the 1st thread is 4 MB, and the download length of the third thread is 2 MB.

Download start position: thread id * length of data downloaded by each thread =?

Download end position: (thread id + 1) * length of data downloaded by each thread-1 =?

 

(3) use the Range header field of Http to specify the position where each thread starts to download files and where to download files,

For example, the file is downloaded from 2 MB to 4M-1byte.

The Code is as follows: HttpURLConnection. setRequestProperty ("Range", "bytes = 2097152-4194303 ");

 

(4) save the file and use the RandomAccessFile class to specify where each thread starts to write data from the local file.

RandomAccessFilethreadfile = newRandomAccessFile ("QQWubiSetup.exe", "rwd ");

Threadfile. seek (2097152); // from where the file is written

 

/*** Multi-Thread download, UI update class * @ author young **/public class MultiThreadDownload extends Thread {private static final String TAG = "MultiThreadDownload "; /** the size of each thread to be downloaded */private int blockSize;/the default number of *** threads is 5. */private int threadNum = 5; /***** file size */private int fileSize;/***** File url, thread number, file name */private String UrlStr, ThreadNo, fileName;/*** saved path */private String SavePath;/** download percentage */private int downloadPercent = 0;/** average download speed */private int downloadSpeed = 0; /** download time */private int usedTime = 0;/** current time */private long curTime; /** whether the download has been completed */private boolean completed = false; private Handler handler; /*** download constructor * @ param url request the download URL * @ param handler UI update the path to save the file using * @ param savePath */public MultiThreadDownload (Handler handler, string url, String saveP Ath) {this. handler = handler; this. urlStr = url; this. savePath = savePath; Log. e (TAG, toString () ;}@ Override public void run () {FileDownloadThread [] fds = new FileDownloadThread [threadNum]; // set the number of threads. try {URL url = new URL (UrlStr); URLConnection conn = url. openConnection (); fileSize = conn. getContentLength (); this. fileName = FileUtil. getFileName (UrlStr); // create only one File, saveFile download content File saveFile = n Ew File (savePath + "/" + fileName); Log. e (TAG, "file Total:" + fileSize + "savePath" + savePath + "fileName" + fileName); RandomAccessFile accessFile = new RandomAccessFile (saveFile, "rwd "); // set the length of the local file to be the same as that of the downloaded file. setLength (fileSize); accessFile. close (); // Handler updates the UI and sends the message sendMsg (FileUtil. startDownloadMeg); // blockSize = (fileSize % threadNum) = 0) of data downloaded by each thread )? (FileSize/threadNum) :( fileSize/threadNum + 1); Log. e (TAG, "download each thread separately:" + blockSize); for (int I = 0; I <threadNum; I ++) {int curThreadEndPosition = (I + 1 )! = ThreadNum? (I + 1) * blockSize-1): fileSize; FileDownloadThread fdt = new FileDownloadThread (url, saveFile, I * blockSize, curThreadEndPosition); fdt. setName ("thread" + I); fdt. start (); fds [I] = fdt;}/*** get the data and update the UI until all download threads have downloaded the data. */Boolean finished = false; // the start time, which is placed out of the loop. usedTime is the total time long startTime = System. currentTimeMillis (); while (! Finished) {downloadSize = 0; finished = true; for (int I = 0; I <fds. length; I ++) {downloadSize + = fds [I]. getDownloadSize (); if (! Fds [I]. isFinished () {finished = false ;}} downloadPercent = (downloadSize * 100)/fileSize; curTime = System. currentTimeMillis (); System. out. println ("curTime =" + curTime + "downloadSize =" + downloadSize + "usedTime" + (int) (curTime-startTime)/1000); usedTime = (int) (curTime-startTime)/1000); if (usedTime = 0) usedTime = 1; downloadSpeed = (downloadSize/usedTime)/1024; sleep (1000 ); /* refresh the interface once every second */sendMsg (FileUtil. updateDownloadMeg);} Log. e (TAG, "download completed"); completed = true; sendMsg (FileUtil. endDownloadMeg);} catch (Exception e) {Log. e (TAG, "multi file error Exception" + e. getMessage (); e. printStackTrace ();} super. run ();}/*** get the file size * @ return */public int getFileSize () {return this. fileSize;}/*** get the downloaded quantity * @ return */public int getDownloadSize () {return this. downloadSize;}/*** get download percentage * @ return */public int getDownloadPercent () {return this. downloadPercent;}/*** get download speed * @ return */public int getDownloadSpeed () {return this. downloadSpeed;}/*** modify the default number of threads * @ param threadNum */public void setThreadNum (int threadNum) {this. threadNum = threadNum;}/*** mark of multipart download completion * @ return */public boolean isCompleted () {return this. completed ;}@ Override public String toString () {return "MultiThreadDownload [threadNum =" + threadNum + ", fileSize =" + fileSize + ", UrlStr =" + UrlStr + ", threadNo = "+ ThreadNo +", savePath = "+ savePath +"] ";}/*** send a message. The user prompts **/private void sendMsg (int what) {Message msg = new Message (); msg. what = what; handler. sendMessage (msg );}
Public class FileDownloadThread extends Thread {private static final String TAG = "FileDownloadThread";/** buffer */private static final int BUFF_SIZE = 1024; /** download URL */private URL;/** cached FIle */private File file;/** start position */private int startPosition; /** end position */private int endPosition;/** current position */private int curPosition;/** completed */private boolean finished = false; /** how many files have been downloaded */private int downloadSize = 0;/***** multipart file download, you can create a multi-threaded mode * @ param url to download the URL * @ param file to download the file * @ param startPosition start position * @ param endPosition end position */public FileDownloadThread (URL url, file file, int startPosition, int endPosition) {this. url = url; this. file = file; this. startPosition = startPosition; this. curPosition = startPosition; this. endPosition = endPosition; Log. e (TAG, toString () ;}@ Override public void run () {BufferedInputStream bis = null; RandomAccessFile rAccessFile = null; byte [] buf = new byte [BUFF_SIZE]; URLConnection conn = null; try {conn = url. openConnection (); conn. setConnectTimeout (10000); // set the timeout conn. setreadtimeouts (10000); conn. setAllowUserInteraction (true); System. out. println (this. getName () + "startPosition" + startPosition + "endPosition" + endPosition); conn. setRequestProperty ("Range", "bytes =" + (startPosition) + "-" + endPosition); // obtain the remaining undownloaded rAccessFile = new RandomAccessFile (file, "rwd"); // read/write // set the position where data is written. seek (startPosition); bis = new BufferedInputStream (conn. getInputStream (), BUFF_SIZE); while (curPosition
 
  
EndPosition) {// If the download is too large, the excess part of System. out. println ("curPosition> endPosition !!!! "); Int extraLen = curPosition-endPosition; downloadSize + = (len-extraLen + 1);} else {downloadSize + = len;} this. finished = true; // Log of download completion in the current phase. e (TAG, "current" + this. getName () + "download completed");} catch (Exception e) {Log. e (TAG, "download error Exception" + e. getMessage (); e. printStackTrace ();} finally {// disable stream FileUtil. closeInputStream (bis); try {rAccessFile. close ();} catch (IOException e) {// TODO Auto-generated catch block Log. e ("AccessFile", "AccessFile IOException" + e. getMessage () ;}} super. run ();}/*** whether the current segment download is complete * @ return */public boolean isFinished () {return finished ;} /*** number of downloads * @ return */public int getDownloadSize () {return downloadSize;} @ Override public String toString () {return "FileDownloadThread [url =" + url + ", file =" + file + ", startPosition =" + startPosition + ", endPosition =" + endPosition + ", curPosition = "+ curPosition +", finished = "+ finished +", downloadSize = "+ downloadSize +"] ";}
 

Multi-threaded download is a multipart download. When a file is created and saved, the sub-thread writes data through the RandomAccessFile class.

 


Sample source code: demo download

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.