Edgio

File Upload End-to-End Examples

This section shows Python code examples that you can use for obtaining a token, uploading a file, and verifying the file was uploaded successfully. Note that rhe verification step is important because it verifies that the file you attempted to upload indeed was uploaded. For example if you attempted to upload a 10MB file and a network error occurred you need to determine if the upload was successful.
You can copy and paste the code into the Python IDE of your choice, or you can use the same concepts to upload files by creating programs in other languages such as Java, JavaScript, and C#.

Obtain a Token

JSON
1>>> import jsonrpclib
2>>> api = jsonrpclib.Server('https://{Account name}.upload.llnw.net/jsonrpc2')
3>> token, uid_gid = api.login('yourUser', 'yourPassword')
4>>> print (token)
5f3037573-2a6f-4042-ab8f-82d6823b0480
For complete details about login, see Logging in Using the JSON-RPC Interface.
HTTP Example
JSON
1>>> import requests
2>>> auth_headers = { 'X-Agile-Username': 'yourUser', 'X-Agile-Password': 'yourPassword' }
3>>> url = 'https://{Account name}.upload.llnw.net/account/login'
4>>> r = requests.post(url, headers=auth_headers)
5>>> token = r.headers['x-agile-token']
6>>> print (token)
77c164371-d581-4068-8ce1-4d17b6a9d8a3
For complete details about account/login, see Logging in Using the HTTP Interface.

/post/file Example

This section presents a simple example using only the X-Agile-Authorization header along with the uploadFile, basename, and directory form fields. Note that uploadFile is a multipart/form-data encoded payload so it is handled differently than other form fields.
For complete details about /post/file, see Web Browser Upload.
Upload a File
1>>> import requests
2>>> basename = 'file1.txt'
3>>> file_to_upload ='/' + basename
4>>> upload_headers = { 'X-Agile-Authorization': token}
5>>> payload = {'basename': basename, 'directory': '/zz' }
6>>> files = { 'uploadFile': open(file_to_upload, 'r') }
7>>> r = requests.post('http://{Account name}.upload.llnw.net/post/file', data=payload, headers=upload_headers, files=files, verify=False)
Verify That the Upload Was Successful
You can use HTTP or JSON-RPC.
HTTP Example
Look at the headers returned from the request. The /post/raw request returns the upload status in the X-Agile-Status header. A value of 0 (zero) means success.
1>>> print (r.headers
2{'x-agile-status': '0', 'content-length': '0', 'access-control-allow-headers': 'X-Agile-Authorization, X-Content-Type', 'x-agile-checksum': 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', 'keep-alive': 'timeout=5, max=100', 'server': 'Apache', 'x-agile-size': '0', 'connection': 'Keep-Alive', 'date': 'Mon, 17 Aug 2015 20:23:17 GMT', 'x-agile-path': '/{Account name}/zz/file1.txt', 'access-control-allow-origin': '*', 'access-control-allow-methods': 'OPTIONS', 'content-type': 'text/json;charset=utf-8'}
For other status codes, see HTTP Response Codes and Request Status Codes.
You can also issue a HEAD request against the object and look at the overall response code (200=OK) as well as the X-Agile-Checksum and Content-Length response headers:
1>>> r = requests.head('http://global.mt.lldns.net/<Account Name>/zz/file1.txt')
2>>> print (r)
3<Response [200]>
4>>> print (r.headers)
5{'x-agile-checksum': 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', 'accept-ranges': 'bytes', 'server': 'nginx/1.6.2', 'last-modified': 'Mon, 17 Aug 2015 20:23:17 GMT', 'connection': 'keep-alive', 'date': 'Mon, 17 Aug 2015 20:33:02 GMT', 'content-type': 'text/plain'}
JSON-RPC Example
Use the stat function to get information on the uploaded file. The stat function has an optional ‘detail’ parameter. Pass True for extended information, or pass False (or omit) for an abbreviated response. A value of 0 in the returned code field indicate success. Other values indicate failure. You can also look at other fields such as size and checksum and compare them to known values.
1>>> api.stat(token, 'zz/file1.txt', True)
2{u'mimetype': u'text/plain', u'code': 0, u'uid': 12020, u'checksum': u'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855', u'gid': 100, u'mtime': 1439842997, u'size': 0, u'type': 2, u'ctime': 1439842997}
For more information about the stat call, see Obtain File or Directory Metadata.
Complete HTTP Example
This section ties information together, providing a complete Python work sample that you can quickly and easily copy and paste into a Python file.
Always use https for logging in to prevent sniffer attacks that can detect your credentials and token.
1import jsonrpclib
2import requests
3api = jsonrpclib.Server('https://{Account Name}.upload.llnw.net/jsonrpc')
4token, user = api.login('yourUser', 'yourPassword')
5
6basename = 'file1.txt'
7file_to_upload ='/' + basename
8upload_headers = { 'X-Agile-Authorization': token}
9payload = {'basename': basename, 'directory': '/zz' }
10files = { 'uploadFile': open(file_to_upload, 'r') }
11r = requests.post('http://{Account name}.upload.llnw.net/post/file', data=payload, headers=upload_headers, files=files, verify=False)
12print (r)
13print (r.headers)
14r2 = requests.head('http://global.mt.lldns.net/{Account Name}/zz/file1.txt')
15print (r2)
16print (r2.headers)
17api.stat(token, '/zz/file1.txt', True)

/post/raw Example

This section presents a simple example using only the X-Agile-Authorization, X-Agile-Basename, and X-Agile-Directory headers.
For complete details about /post/raw, see File Raw Post.
Upload a File
1>>> import requests
2>>> file_to_upload = '\test.mp3'
3>>> upload_headers = { 'X-Agile-Authorization': token, 'X-Agile-Basename': file_to_upload, 'X-Agile-Directory': '/' }
4>>> with open(file_to_upload, 'rb') as filesrc:
5 r = requests.post('http://{Account name}.upload.llnw.net/post/raw', data=filesrc, headers=upload_headers)
Verify That the Upload Was Successful
You can use HTTP or JSON-RPC.
HTTP Example
Look at the headers returned from the request. The /post/raw request returns the upload status in the X-Agile-Status header. A value of 0 means success.
1>>> print (r.headers
2{'x-agile-status': '0', 'content-length': '0', 'access-control-allow-headers': 'X-Agile-Authorization, X-Content-Type', 'x-agile-checksum': 'f5d56bded9d953c31d4e257ecf606e152435af1c8139d32a5b367e9070ac783f', 'keep-alive': 'timeout=5, max=100', 'server': 'Apache', 'x-agile-size': '594472', 'connection': 'Keep-Alive', 'date': 'Mon, 17 Aug 2015 17:10:23 GMT', 'x-agile-path': '/{Account Name}/test.mp3', 'access-control-allow-origin': '*', 'access-control-allow-methods': 'OPTIONS', 'content-type': 'text/json;charset=utf-8'}
You can also issue a HEAD request against the object and look at the headers returned and the overall response code (200=OK).
Here is an example using the Python requests library:
1>>> r2 = requests.head('http://{Account name}.upload.llnw.net/{Account Name}/' + basename)
2>>> print (r2)
3<Response [200]>
4>>> print (r2.headers)
5{'content-length': '594472', 'x-agile-checksum': 'f5d56bded9d953c31d4e257ecf606e152435af1c8139d32a5b367e9070ac783f', 'accept-ranges': 'bytes', 'server': 'nginx/1.6.2', 'last-modified': 'Mon, 17 Aug 2015 17:10:25 GMT', 'connection': 'keep-alive', 'date': 'Mon, 17 Aug 2015 17:15:07 GMT', 'content-type': 'audio/mpeg'}
JSON-RPC Example
Use the stat function to get information on the uploaded file. The stat function has an optional ‘detail’ parameter. Pass True for extended information, or pass False (or omit) for an abbreviated response. A value of 0 in the returned code field indicate success. Other values indicate failure. You can also look at other fields such as size and checksum and compare them to known values.
1>>> api.stat(token, '/test.mp3', True)
2{u'mimetype': u'audio/mpeg', u'code': 0, u'uid': 12020, u'checksum': u'f5d56bded9d953c31d4e257ecf606e152435af1c8139d32a5b367e9070ac783f', u'gid': 100, u'mtime': 1439831425, u'size': 594472, u'type': 2, u'ctime': 1439831425}
For more information about the stat call, see Obtain File or Directory Metadata.
Complete HTTP Example
This section ties information together, providing a complete Python working sample that you can quickly and easily copy and paste into a Python file.
Always use https for logging in to prevent sniffer attacks that can detect your credentials and token.
1import jsonrpclib
2import requests
3api = jsonrpclib.Server('https://{Account Name}.upload.llnw.net/jsonrpc')
4token, user = api.login('yourUser', 'yourPassword')
5
6basename = 'test.mp3'
7file_to_upload ='/' + basename
8upload_headers = { 'X-Agile-Authorization': token, 'X-Agile-Basename': file_to_upload, 'X-Agile-Directory': '/' }
9with open(file_to_upload, 'rb') as filesrc:
10 r = requests.post('http://{Account name}.upload.llnw.net/post/raw', data=filesrc, headers=upload_headers)
11print (r.headers
12r2 = requests.head('http://global.mt.lldns.net/{Account Name}/' + basename)
13print (r2)
14print (r2.headers)
15api.stat(token, "/" + basename, True)

Multipart Example

This section presents a simple scenario for initiating a multipart upload, adding a piece to the upload, and completing the upload. For complete information about multipart uploads, see Uploading Files — Multipart.
Calculate the SHA-256 Checksum For the File
You can use the value later to ensure the file was uploaded successfully.
Initiate the Upload
1>>> import requests
2>>> serverDirectory = '/multipart'
3>>> uploadBasename = 'text-file1.txt'
4>>> headers = { 'X-Agile-Authorization': token, 'X-Agile-Basename': uploadBasename, 'X-Agile-Directory': serverDirectory}
5>>> r = requests.post('http://[Account name]-l.upload.llnw.net/multipart/create', headers=headers, verify=False)
Verify That the Initiation Was Successful
Look at the headers returned from the request. The /multipart/create request returns the upload status in the X-Agile-Status header. A value of 0 means success.
1>>> print (r.headers)
2{'x-agile-status': '0', 'content-length': '0', 'x-agile-meta': 'content_type=None mtime=0', 'keep-alive': 'timeout=5, max=100', 'server': 'Apache', 'connection': 'Keep-Alive', 'x-agile-multipart': 'e20207caa6234b53a93f671320ad7be6', 'date': 'Wed, 19 Aug 2015 21:23:41 GMT', 'x-agile-path': '/{Account Name}/multipart/text-file1.txt', 'access-control-allow-origin': '*', 'access-control-allow-methods': 'OPTIONS', 'content-type': 'text/json;charset=utf-8', 'access-control-allow-headers': 'X-Agile-Authorization, X-Content-Type'}
A multipart upload is not available until you have added pieces to it and completed it, so a HEAD request or a JSON-RPC stat request on the object at this point will fail.
Add a Piece To the Multipart Upload
This is a simple example that adds a complete file to the multipart upload. In real life you would stream the object, break the stream into chunks and upload each chunk as a piece.
1>>> mpid = r.headers['X-Agile-Multipart']
2>>> pieceBasename = 'file1.txt'
3>>> file_to_upload ='/' + pieceBasename
4>>> headers = { 'X-Agile-Authorization': token, 'X-Agile-Multipart': mpid, 'X-Agile-Part': '1'}
5>>> with open(file_to_upload, 'rb') as filesrc:
6>>> r2 = requests.post('http://[Account name]-l.upload.llnw.net/multipart/piece', data=filesrc, headers=headers, verify=False)
Verify That the Piece Was Uploaded Successfully
Look at the headers returned from the request. The upload status is in the X-Agile-Status header. A value of 0 means success.
Compare the checksum (X-Agile-Checksum header) with the value you calculated earlier.
1>>> print (r2.headers)
2{'x-agile-status': '0', 'content-length': '0', 'access-control-allow-headers': 'X-Agile-Authorization, X-Content-Type', 'x-agile-checksum': 'c28a4e896970557bea969cc591299183b341d90dad44ace3684994be80e8d07c', 'keep-alive': 'timeout=5, max=100', 'server': 'Apache', 'x-agile-size': '70', 'connection': 'Keep-Alive', 'date': 'Wed, 19 Aug 2015 21:23:46 GMT', 'access-control-allow-origin': '*', 'access-control-allow-methods': 'OPTIONS', 'content-type': 'text/json;charset=utf-8'}
Complete the Upload
1>>> headers = { 'X-Agile-Authorization': token, 'X-Agile-Multipart': mpid}
2>>> r3 = requests.post('http://[Account name]-l.upload.llnw.net/multipart/complete', headers=headers, verify=False)
Verify That the Upload Was Successful
You can use HTTP or JSON-RPC.
HTTP Example
Look at the X-Agile-Status header. A value of 0 means success.
1>>> print (r3.headers)
2{'x-agile-status': '0', 'content-length': '0', 'x-agile-parts': '1', 'keep-alive': 'timeout=5, max=100', 'server': 'Apache', 'connection': 'Keep-Alive', 'X-Agile-Multipart': 'e20207caa6234b53a93f671320ad7be6', 'date': 'Wed, 19 Aug 2015 21:23:50 GMT', 'access-control-allow-origin': '*', 'access-control-allow-methods': 'OPTIONS', 'content-type': 'text/json;charset=utf-8', 'access-control-allow-headers': 'X-Agile-Authorization, X-Content-Type'}
You can also issue a HEAD request against the object and look at the headers returned and the overall response code (200=OK).
1>>> r4 = requests.head('http://{Account name}.upload.llnw.net' + serverDirectory + '/' + uploadBasename)
2>>> print (r4)
3<Response [200]>
4>>> print (r4 headers)
5{'content-length': '70', 'x-agile-checksum': 'c28a4e896970557bea969cc591299183b341d90dad44ace3684994be80e8d07c', 'accept-ranges': 'bytes', 'server': 'nginx/1.6.2', 'last-modified': 'Wed, 19 Aug 2015 21:22:44 GMT', 'connection': 'keep-alive', 'date': 'Wed, 19 Aug 2015 21:23:53 GMT', 'content-type': 'text/plain'}
There is often a delay between the time you complete the multipart upload and the time it is ready for a HEAD request. Issuing a HEAD request too soon results in a 404 (not found) error.
JSON-RPC Example
Use the stat function to get information on the uploaded file. The stat function has an optional ‘detail’ parameter. Pass True for extended information, or pass False (or omit) for an abbreviated response. A value of 0 in the returned code field indicate success. Other values indicate failure. You can also look at other fields such as size and checksum and compare them to known values.
1>>> api.stat(token, serverDirectory + '/' + uploadBasename, True)
2{u'mimetype': u'text/plain', u'code': 0, u'uid': 12020, u'checksum': u'c28a4e896970557bea969cc591299183b341d90dad44ace3684994be80e8d07c', u'gid': 100, u'mtime': 1440025478, u'size': 70, u'type': 2, u'ctime': 1440025489}
For more information about the stat call, see Obtain File or Directory Metadata.
Complete HTTP Example
This section ties information together, providing a complete Python working sample that you can quickly and easily copy and paste into a Python file.
Always use https for logging in to prevent sniffer attacks that can detect your credentials and token.
1import jsonrpclibimport requests
2import os
3 
4######################################
5
6# Log in
7######################################
8api = jsonrpclib.Server('https://{Account Name}.upload.llnw.net/jsonrpc')
9token, user = api.login('yourUser', 'yourPassword')
10 
11######################################
12# Set Upload Variables
13######################################
14serverDirectory = '/multipart'
15localDirectory = '/Temp/'
16fileName = 'flat-irons3.jpg'
17chunkSize = 200000
18 
19print ('==================')
20print ('Upload Information')
21print ('==================')
22print ('Upload file: ' + fileName)
23print (' Server Dir: ' + serverDirectory)
24print (' Piece Size: ' + str(chunkSize))
25print ('')
26 
27######################################
28# Create multipart
29######################################
30print ('================')
31print ('Multipart Create')
32print ('================')
33 
34headers = { 'X-Agile-Authorization': token, 'X-Agile-Basename': fileName, 'X-Agile-Directory': serverDirectory}
35r = requests.post('http://{Account Name}.upload.llnw.net/multipart/create', headers=headers, verify=False)
36 
37print ('Request Result')
38print ('--------------')
39print (str (r.status_code ) + ' (' + r.reason + ')')
40 
41print ('')
42print ('Multipart ID')
43print ('------------')
44mpid = r.headers['X-Agile-Multipart']
45print (mpid)
46 
47######################################
48# Multipart Piece
49######################################
50print ('')
51
52print ('===============')
53print ('Multipart Piece')
54print ('===============')
55file_to_upload = localDirectory + fileName
56pieceNum = 1
57f = open(file_to_upload, 'rb')
58while True:
59  chunkBuff = f.read( chunkSize )
60  if not chunkBuff:
61    break
62  else:
63    headers = { 'X-Agile-Authorization': token, 'X-Agile-Multipart': mpid, 'X-Agile-Part': str( pieceNum )}
64    print (' Sending piece: ' + str( pieceNum ) )
65    r2 = requests.post('http://{Account Name}.upload.llnw.net/multipart/piece', data=chunkBuff, headers=headers, verify=False)
66    print (' Result: ' + str (r2.status_code ) + ' (' + r2.reason + ')')
67    status = r2.headers['X-Agile-Status']
68    print ('X-Agile-Status: ' + str( status ))
69    print ('------------------------')
70    if status != "0":
71       break
72    else:
73      pieceNum = pieceNum +1
74f.close()
75 
76######################################
77# Multipart Complete
78######################################
79print ('')
80print ('==================')
81print ('Multipart Complete')
82print ('==================')
83headers = { 'X-Agile-Authorization': token, 'X-Agile-Multipart': mpid}
84r3 = requests.post('http://{Account Name}.upload.llnw.net/multipart/complete', headers=headers, verify=False)
85print ('Request Result')
86print ('--------------')
87print (str (r3.status_code ) + ' (' + r3.reason + ')')
88print ('X-Agile-Status: ' + r3.headers['x-agile-status'])
89 
90######################################
91# Sleep
92######################################
93from time import sleep
94secs = 5
95print ('')
96print ('**sleeping for ' + str(secs) + ' seconds...')
97sleep( secs )
98 
99######################################
100# HEAD Request
101######################################
102print ('==================')
103print ('HEAD Request')
104print ('==================')
105print ('HEAD request on ' + serverDirectory + '/' + fileName)
106r4 = requests.head('http://{Account name}.upload.llnw.net' + serverDirectory + '/' + fileName)
107print ('Request Result')
108print ('--------------')
109print (str (r4.status_code ) + ' (' + r4.reason + ')')
110print ('')
111print ('Checksum')
112print ('--------')
113print (r4.headers['x-agile-checksum'])
114print ('')
115print ('Content Length')
116print ('--------------')
117print (r4.headers['content-length'])
118 
119######################################
120# JSON-RPC stat Request
121######################################
122print ('')
123print ('=====================')
124print ('JSON-RPC stat Request')
125print ('=====================')
126print ('Requesting stat on ' + serverDirectory + '/' + fileName)
127results = api.stat(token, serverDirectory + '/' + fileName, True))
128print ('')
129print ('Request Result')
130print ('--------------')
131print (str (results['code'] ))
132statChecksum = results['checksum']
133print ('')
134print ('Checksum')
135print ('--------')
136print (statChecksum)
137print ('')
138print ('File Size')
139print ('---------')
140print (results['size'])
141 
142########################################
143# Get the SHA-256 hash of the local file
144########################################
145import hashlib
146fh = None
147try:
148  fh = open(file_to_upload, 'rb')
149except IOError, e:
150  log.warn("checksum_file IOError: %s: %s" % (file_to_upload, e))
151  fh = None
152if fh != None:
153  m = hashlib.sha256()
154  while True:
155    buf = fh.read(4096)
156    if not buf:
157      break
158    m.update(buf)
159  fh.close()
160  localFileCkSum = m.hexdigest()
161  print ('')
162  print ('==========')
163  print ('Local file')
164  print ('==========')
165  print ('Checksum')
166  print ('--------')
167  print (localFileCkSum)
168 
169fileSize = os.path.getsize(file_to_upload)
170print ('')
171print ('File Size')
172print ('---------')
173print (fileSize)
174print ('')
175if statChecksum == localFileCkSum:
176  print ('Local file checksum matches checksum from stat call.')
177else:
178  print ('Local file checksum does not match checksum returned from stat call.')
179 
180########
181#Log out
182########
183api.logout(token)