forked from DarkStarSword/junk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
wget2axel.py
executable file
·69 lines (58 loc) · 2.13 KB
/
wget2axel.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#!/usr/bin/env python
def url_size(url):
import httplib, urllib2
proto, url = urllib2.splittype(url)
assert(proto.lower() == 'http')
host, path = urllib2.splithost(url)
# http://stackoverflow.com/questions/107405/how-do-you-send-a-head-http-request-in-python
conn = httplib.HTTPConnection(host)
conn.request('HEAD', path)
res = conn.getresponse()
# FIXME: Follow any redirects
return int(res.getheader('content-length'))
def axel_divide(size, num_connections):
chunk_size = size // num_connections
ret = [[0, chunk_size - 1]]
for i in range(1, num_connections):
start_byte = ret[i-1][1] + 1
ret.append([start_byte, start_byte + chunk_size])
ret[-1][1] = size - 1
print ret
return ret
def adjust_connection_current_bytes(filesize, connections):
for (i, (start_byte, end_byte)) in enumerate(connections):
if start_byte < filesize:
connections[i][0] = filesize
print connections
return connections
def save_axel_state(state_filename, filesize, connections):
import struct
f = open(state_filename, 'w')
f.write(struct.pack('i', len(connections))) # Two separate writes
f.write(struct.pack('q', filesize)) # to avoid padding
for (start_byte, end_byte) in connections:
f.write(struct.pack('q', start_byte))
f.close()
def pad_file(filename, length):
f = open(filename, 'w')
f.truncate(length)
f.close()
if __name__ == '__main__':
import sys, os
url = sys.argv[1]
filename = sys.argv[2]
state_filename = '%s.st' % filename
if os.path.exists(state_filename):
print 'Axel state file already exists - aborting!'
sys.exit(1)
length = url_size(url)
filesize = os.stat(filename).st_size
print '%i / %i (%i bytes to go)' % (filesize, length, length - filesize)
assert(filesize < length)
target_connections = 4
num_connections = length // ((length - filesize) // target_connections)
print 'Telling axel to use %i connections (%.2f are already complete)' % (num_connections, filesize / (float(length) / num_connections))
connections = axel_divide(length, num_connections)
connections = adjust_connection_current_bytes(filesize, connections)
save_axel_state(state_filename, filesize, connections)
# pad_file(filename, length)