Code recipe : Download Manager (Python Version)

Recently I had published my blog post Building a Download Manager(in JAVA). And I am presenting the python implementation of download manager. The whole concept is same except the language of implementation. You can check the older JAVA implementation here.
Python has nice libraries urllib and urllib2 we can use for our purpose. urllib2 provides nice feature of request header modification. Here's my recipe python version.
import urllib2
from threading import Thread
class Downloader:
    def __init__(self):
    def downloadFile(self, url, num_streams, dest_fname):
        file_size = self.getContentLength(url)
        if not self.supportsPartialContent(url):
            print "The server doesn't support partial content!! Resuming with Single Stream"
            self.downloadStream(url, dest_fname, "bytes=0-"+`file_size`)
        initial = 0
        block   = int(file_size / num_streams)
        final   = block
        files   = []
        threads = []
        for i in xrange(num_streams):
            drange  = "bytes=" + `initial` + "-" + `final`
            print drange
            files.append("fileparts" + `i`)
            t = Thread(target=self.downloadStream, args=(url, files[i], drange))
            initial = final
            final   = (final + block) if (i < num_streams-2) else file_size
        [t.start()  for t in threads]
        [t.join()   for t in threads]
        self.concatFiles(files, dest_fname);
    def concatFiles(self, original, dest):
        final_file = open(dest, 'wb')
        for f in original:
            fopener = open(f, 'rb')
    def supportsPartialContent(self, url):
        request = urllib2.Request(url)
        request.add_header("Range", "bytes=0-10")
        opener  = urllib2.urlopen(request)
        print opener.getcode()
        return True if opener.getcode() == 206 else False
    def downloadStream(self, url, file_name, range):
        request = urllib2.Request(url)
        request.add_header("Range", range)
        opener  = urllib2.urlopen(request)
        f = open(file_name, "wb")
    def getContentLength(self, url):
        content = urllib2.urlopen(url)
        meta =
        file_size = int(meta.getheaders("Content-Length")[0])
        return file_size
url = ""
num_streams = 5
dest_fname = "testfile"
dman = Downloader()
dman.downloadFile(url, num_streams, dest_fname)
I suggest you take only the concept and try make your own recipe. Happy coding guys.

1 comment :