download a file in java using multi threading
transferTo
is thread safe so you can only call it from one thread at a time.
If you want to read multiple parts of a file at once, the server has to support this and you need a stream for each portion of the file you are downloading.
For information on how to read portions of a file
Downloading a portion of a File using HTTP Requests
Reading the first part of a file using HTTP
Behzad Hassani
Web Programmer and Developer Web Template Designer
Updated on June 04, 2022Comments
-
Behzad Hassani almost 2 years
I'm working on a downloader similar to IDM, I hava read This post about it. and I have implement my first-steps of code.
Here is the Downloader Class's Code:
package download.manager; import java.io.FileOutputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.nio.channels.ReadableByteChannel; import java.util.logging.Level; import java.util.logging.Logger; public class Downloader implements Runnable{ private String url; private int num; private long start; private long end; ReadableByteChannel rbc; public Downloader(String url, int num, long start, long end, ReadableByteChannel rbc) { this.url = url; this.num = num; this.start = start; this.end = end; this.rbc = rbc; } @Override public void run() { download(); } private void download(){ try { System.out.println(num + " is executing"); URL file = new URL(url); FileOutputStream stream = new FileOutputStream("tmp"+num); stream.getChannel().transferFrom(rbc, start, end); } catch (MalformedURLException ex) { Logger.getLogger(Downloader.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(Downloader.class.getName()).log(Level.SEVERE, null, ex); } } }
and this is my main function:
package download.manager; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; /** * * @author Behzad */ public class DownloadManager { /** * @param args the command line arguments */ public static void main(String[] args) { URL file = null; ReadableByteChannel rbc = null; try { String url = "http://dl1.video.varzesh3.com/video/clip93/12/video/havashi/top5_save_derby_dortmond.mp4"; file = new URL(url); rbc = Channels.newChannel(file.openStream()); int size = file.openConnection().getContentLength(); ExecutorService pool = Executors.newFixedThreadPool(4); int partSize = size / 4; pool.submit(new Downloader(url, 1, 0, partSize, rbc)); pool.submit(new Downloader(url, 2, partSize, partSize, rbc)); pool.submit(new Downloader(url, 3, 2 * partSize, partSize, rbc)); pool.submit(new Downloader(url, 4, 3 * partSize, partSize, rbc)); pool.shutdown(); pool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS); } catch (MalformedURLException | InterruptedException ex) { Logger.getLogger(DownloadManager.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(DownloadManager.class.getName()).log(Level.SEVERE, null, ex); } } }
but when I run this code the downloader downloads just first part of file. as you see in the picture
what should I do for this ?
Here is updated download method :
private void download(){ try { System.out.println(num + " is executing"); URL file = new URL(url); ReadableByteChannel rbc = Channels.newChannel(file.openStream()); FileOutputStream stream = new FileOutputStream("tmp"+num); stream.getChannel().transferFrom(rbc, start, end); } catch (MalformedURLException ex) { Logger.getLogger(Downloader.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(Downloader.class.getName()).log(Level.SEVERE, null, ex); } }
-
Behzad Hassani about 9 yearsThen You say I shoud define 4 ReadableByteChannel ? But I hava did it and nothing changed !
-
Vishy about 9 years@BehzadHassani can you update your code to reflect this?
-
Vishy about 9 years@BehzadHassani you have to tell the server to download different portions of the file, or you will just down the entire file 5 times.
-
Behzad Hassani about 9 yearsNo Of course I want to download multiple portions of file @Peter Lawrey
-
Vishy about 9 years@BehzadHassani In that case you need to set
urlConnection.setRequestProperty("Range", "Bytes=0-24");
to set the byte range you want to download. See the first link for more details. Note: the server might not accept this option. -
Behzad Hassani about 9 yearsThank you Peter, I will check it :) @Peter Lawrey