Java for large file download (HTTP mode)

Source: Internet
Author: User
Tags httpcontext save file

Java implementation of large file download, based on HTTP, control God horse will not say.

Idea: The download file is nothing but to read the file and then write the file, mainly these two steps, the main difficulty:

1. Read the file, is the hard disk to the memory process, due to the JDK memory limit, can not read too large.

2. Write a file, is to respond to the browser side of the process, the HTTP protocol is a short link, if the file is too slow to write, the time is too long, it will cause the browser to die.


Knowledge Points:

The 1.org.apache.http.impl.client.closeablehttpclient analog httpclient client sends an HTTP request that can control the byte location of the requested file.

2.BufferedInputStream is familiar with using it to accept requests for streaming information caching.

The 3.RandomAccessFile file is a random class that can write stream information to a file at a specified location.


Based on the above information, my implementation of the idea is to first determine the size of the download file, with multi-threaded segmentation custom HTTP request quantity and request content, response to write to Randomaccessfile in the specified location. In the vulgar point is the large HTTP partition into a small HTTP request, equivalent to each request a Web page.

Nonsense not to say, on the code.



Downloadmanagertest class:

package xxxx;import java.io.file;import java.io.ioexception;import  java.io.randomaccessfile;import java.net.httpurlconnection;import java.net.url;import  java.util.concurrent.countdownlatch;import org.apache.commons.lang.exception.exceptionutils;import  Org.apache.http.impl.client.closeablehttpclient;import org.apache.http.impl.client.httpclients;import  org.apache.http.impl.conn.PoolingHttpClientConnectionManager;import org.junit.After;import  org.junit.before;import org.junit.test;import org.junit.runner.runwith;import org.slf4j.logger; Import org.slf4j.loggerfactory;import org.springframework.beans.factory.annotation.autowired;import  org.springframework.core.task.TaskExecutor;import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.contextconfiguration;import  Org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;import org.springframework.test.context.junit4.springjunit4classrunner;/** *  *  File download Management class  */@RunWith (Springjunit4classrunner.class) @ActiveProfiles ("Test") @ContextConfiguration (locations={ "Classpath:test/applicationcontext.xml"}) public class downloadmanagertest extends  abstracttransactionaljunit4springcontexttests{private static final logger logger =  loggerfactory.getlogger (Downloadmanagertest.class);/** *  *  the number of bytes downloaded per thread  */ private long unitsize = 1000 * 1024; @Autowiredprivate  TaskExecutor  taskexecutor;private closeablehttpclient httpclient;private long starttimes;private  long endtimes;         @Before     public  Void setup ()  throws exception    {    starttimes =  system.currenttimemillis ();Nbsp;       system.out.println ("Test start ....");    }          @After     public void teardown ()   throws exception    {    endtimes =  System.currenttimemillis ();         system.out.println ("End of test!!");         system.out.println ("********************");         system.out.println ("Total download time:" + (Endtimes-starttimes)/1000+ "s");         system.out.println ("********************");    }public  Downloadmanagertest ()  {system.out.println ("Initialize test class ...."); Poolinghttpclientconnectionmanager cm = new poolinghttpclientconnectionmanager (); Cm.setmaxtotal (+); Httpclient = httpclients.custom (). Setconnectionmanager (CM). Build ();}/** *  *  start multiple threads download file  */@Testpublic  void  dodownload ()  throws  ioexception {string remotefileurl= "Http://{host}:{port}/{project}/xx.xml"; String localpath= "e://test//"; String filename = new url (Remotefileurl). GetFile (); SYSTEM.OUT.PRINTLN ("Remote file name:" +filename); Filename = filename.substring (Filename.lastindexof ("/")   + 1,filename.length ()). Replace ("%20",  " "); SYSTEM.OUT.PRINTLN ("Local file name:" +filename); Long filesize = this.getremotefilesize (Remotefileurl); This.createfile (Localpath+system.currenttimemillis () +filename, filesize); long threadcount =  (filesize/unitsize) + (filesize % unitsize!=0?1:0); long offset  = 0; Countdownlatch end = new countdownlatch (Threadcount.intvalue ());if  (fileSize  <= unitsize)  {//  If the remote file size is less than or equal to unitsizedownloadthreadtest downloadthread = new& nbsp;D ownloadthreadtest (remotefileurl,localpath+filename, offset, filesize,end,httpclient); Taskexecutor.execute (Downloadthread);}  else {//  if the remote file size is greater than unitsizefor  (int i = 1; i <  threadcount; i++)  {downloadthreadtest downloadthread = new downloadthreadtest ( remotefileurl, localpath+filename, offset, unitsize,end,httpclient); TaskExecutor.execute ( Downloadthread); offset = offset + unitsize;} if  (filesize % unitsize != 0)  {//  if not divisible, you need to create another thread to download the remaining bytes Downloadthreadtest  downloadthread = new downloadthreadtest (remotefileurl, localpath+filename,  offset, filesize - unitsize *  (threadCount-1), end,httpclient); Taskexecutor.execute ( Downloadthread);}} Try {end.await ();}  catch  (interruptedexception e)  {logger.error ("downloadmanager exception msg:{}" , ExceptionutiLs.getfullstacktrace (e)); E.printstacktrace ();} System.out.println ("111111"); Logger.debug ("Download done! {}  ", localpath+filename);//return localpath+filename;} /** *  *  get remote File size  */private long getremotefilesize (String  Remotefileurl)  throws IOException {long fileSize = 0; httpurlconnection httpconnection =  (httpurlconnection)  new url (REMOTEFILEURL). OpenConnection (); Httpconnection.setrequestmethod ("HEAD");int responsecode =  Httpconnection.getresponsecode ();if  (responsecode >= 400)  {logger.debug ("Web server response Error!"); return 0;} string sheader;for  (int i = 1;;  i++)  {sheader = httpconnection.getheaderfieldkey (i);if  (sHeader != null  && sheader.equals ("Content-length"))  {system.out.println ("File size contentlength:" +  Httpconnection.getcontentlength ()); Filesize = long.parselonG (Httpconnection.getheaderfield (Sheader)); break;}} Return filesize;} /** *  *  creates a file of the specified size  */private void createfile (string filename,  long filesize)  throws ioexception {file newfile = new file (fileName); Randomaccessfile raf = new randomaccessfile (newfile,  "RW"); Raf.setLength (fileSize); Raf.close ();} Public taskexecutor gettaskexecutor ()  {return taskexecutor;} Public void settaskexecutor (Taskexecutor taskexecutor)  {this.taskExecutor =  Taskexecutor;}}

Downloadthreadtest class:

package xxxx;import java.io.bufferedinputstream;import java.io.file;import  java.io.ioexception;import java.io.randomaccessfile;import java.util.concurrent.countdownlatch; import org.apache.commons.lang.exception.exceptionutils;import  org.apache.http.client.clientprotocolexception;import  Org.apache.http.client.methods.closeablehttpresponse;import org.apache.http.client.methods.httpget;import  org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.httpcontext;import org.slf4j.logger;import  org.slf4j.loggerfactory;/** *  *  is responsible for the file download class  */public class downloadthreadtest  extends Thread {private static final Logger LOGGER =  Loggerfactory.getlogger (Downloadthreadtest.class);/** *  *  files to download  */private  String url = null;/** *  *  Local file name  */private String fileName = null;/** *  *  Offset  */private long offset = 0;/** *  *  number of downloaded bytes assigned to this thread  */ private long length = 0;private countdownlatch end;private  closeablehttpclient httpclient;private httpcontext context;/** *  *  @param  url *             Download file Address  *   *  @param  fileName *              Save file name  *  *  @param  offset *              This thread download offset  *  *  @param  length *              this thread download length  *  *  *  * @ Author angus.wang *  *&nbSp;*/public downloadthreadtest (String url, string file, long offset, long  length,countdownlatch end, closeablehttpclient httpclient)  {this.url = url ; this.filename = file;this.offset = offset;this.length = length;this.end =  end;this.httpclient = httpclient;this.context = new basichttpcontext (); Logger.debug ("offset ="  + offset +  "byte number ="  + length);} Public void run ()  {try {httpget httpget = new httpget (This.url); Httpget.addheader ("Range",  "bytes="  + this.offset +  "-" +  (this.offset +  this.length - 1)); Closeablehttpresponse response = httpclient.execute (Httpget,context); Bufferedinputstream bis = new bufferedinputstream (Response.getentity (). GetContent ()); byte[ ] buff = new byte[1024];int  bytesread; File newfile = new file (FileName); Randomaccessfile raf = new randomaccessfile (newfile,  "RW");while  ((bytesRead  = bis.read (buff, 0, buff.length))  != -1)  {raf.seek (This.offset); Raf.write ( Buff, 0, bytesread); this.offset = this.offset + bytesread;} Raf.close (); Bis.close ();}  catch  (clientprotocolexception e)  {logger.error ("downloadthread exception msg:{} ", Exceptionutils.getfullstacktrace (e));}  catch  (ioexception e)  {logger.error ("downloadthread exception msg:{}", Exceptionutils.getfullstacktrace (e));}  finally {end.countdown (); Logger.info (End.getcount ()  +  " is go on!"); System.out.println (End.getcount ()  +  " is go on!");}}}

Application.xml

<bean id= "Taskexecutor" class= "Org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" ><!-- Thread pool Active threads--><property name= "Corepoolsize" value= "5"/><!--thread Pools maximum active threads--><property name= " Maxpoolsize "value="/><!--the maximum capacity of the queue--><property name= "queuecapacity" value= "ten"/></bean> <bean id= "Downloadmanager" class= "xx. Downloadmanagertest "><property name=" Taskexecutor "ref=" Taskexecutor "/></bean>

Test run, 500M, I have a speed of about half an hour. To download larger files, you can change the maximum queue size indefinitely, as long as the JDK memory is large enough.

If you disagree, you are welcome to correct the great God.

Java for large file download (HTTP mode)

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.