-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtuspy.py
123 lines (105 loc) · 3.41 KB
/
tuspy.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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
from optparse import OptionParser
import os
import sys
import StringIO
import time
import traceback
import requests
import pycurl
import config
#exponential backoff
def attempts(max_attempts=3, initial_delay=10):
for i in range(max_attempts):
yield i
time.sleep(initial_delay ** i)
def die(msg, exit_code=0):
print msg
sys.exit(exit_code)
def get_endpt(filename):
filesize = os.path.getsize(filename)
c = requests.post(config.CREATE_ENDPT, headers={"Upload-Length": filesize, "Tus-Resumable": "1.0.0"})
if c.status_code != 201:
die("create failure. reason: %s" % c.reason)
location = c.headers["Location"]
print location
return location
def get_offset(location):
h = requests.head(location, headers={"Tus-Resumable": "1.0.0"})
offset = int(h.headers["Upload-Offset"])
print "Offset: ", offset
return offset
def upload(location, filename, offset=0, upload_speed=None):
c = None
content_type = "application/offset+octet-stream"
try:
c = pycurl.Curl()
#c.setopt(pycurl.VERBOSE, 1)
c.setopt(pycurl.URL, str(location))
bout = StringIO.StringIO()
hout = StringIO.StringIO()
c.setopt(pycurl.HEADERFUNCTION, hout.write)
c.setopt(pycurl.WRITEFUNCTION, bout.write)
c.setopt(pycurl.UPLOAD, 1)
c.setopt(pycurl.CUSTOMREQUEST, 'PATCH')
f = open(filename, 'rb')
if offset > 0:
f.seek(offset)
c.setopt(pycurl.READFUNCTION, f.read)
filesize = os.path.getsize(filename)
if upload_speed:
c.setopt(pycurl.MAX_SEND_SPEED_LARGE, upload_speed)
c.setopt(pycurl.INFILESIZE, filesize - offset)
c.setopt(pycurl.HTTPHEADER, ["Expect:", "Content-Type: %s" % content_type, "Upload-Offset: %d" % offset, "Tus-Resumable: 1.0.0"])
c.perform()
response_code = c.getinfo(pycurl.RESPONSE_CODE)
response_data = bout.getvalue()
response_hdr = hout.getvalue()
#print response_data
#print response_hdr
print "patch->", response_code
return response_code == 200
finally:
if c: c.close()
parser = OptionParser()
parser.add_option("-f", "--file", dest="filename",
help="file to upload")
parser.add_option("-u", "--upload_speed",
dest="upload_speed", default=None,
help="upload speed in bytes per second")
"""
parser.add_option("-t", "--content-type",
dest="content_type", default="binary/octet-stream",
help="content-type")
"""
(options, args) = parser.parse_args()
if not options.filename:
parser.print_help()
sys.exit(0)
upload_speed = None
try:
if options.upload_speed:
upload_speed = int(options.upload_speed)
except:
parser.print_help()
sys.exit(0)
filename = options.filename
if not os.path.isfile(filename):
die("invalid file %s" % filename)
status = "upload failure"
offset = 0
filesize = os.path.getsize(filename)
location = get_endpt(filename)
for i in attempts():
try:
offset = get_offset(location)
if offset == filesize:
status = "upload success"
break
upload(location, filename, offset=offset, upload_speed=upload_speed)
offset = get_offset(location)
if offset == filesize:
status = "upload success"
break
except:
traceback.print_exc()
die(status)