1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 """Special cleint for uploading and downloading files."""
22
23 import httplib, urlparse
24 import urllib2
25 import os
26 import errno
27 import json
28 import mimetypes
29
30 from u1rest.lib.client import BaseClient
31
32
33 -class ContentClient(BaseClient):
34 """A client used to handle file content Requests."""
35
36
37 download_directory = "content"
38
39 - def get_or_make_download_path(self, path, download_directory=None):
40 """Create local directories for the downloaded files."""
41 if download_directory is None:
42 path = os.path.join(self.download_directory, path)
43 else:
44 _, filename = os.path.split(path)
45 path = os.path.join(download_directory, filename)
46 subdir, _ = os.path.split(path)
47 try:
48 os.makedirs(subdir)
49 except OSError as exc:
50 if exc.errno == errno.EEXIST:
51 pass
52 else: raise
53 return path
54
55 - def get_file(self, path, download_directory=None):
56 """Download a file from an http get."""
57 url = self.get_url_from_path(path, None)
58 request = self._get_authenticated_request(url, None)
59 opener = urllib2.build_opener(urllib2.BaseHandler)
60 response = opener.open(request)
61 file_path = self.get_or_make_download_path(path, download_directory)
62 path = 'content/' + path.lstrip("/")
63 new_file = open(file_path, 'w')
64 block_sz = 8192
65 while True:
66 read_bytes = response.read(block_sz)
67 if not read_bytes:
68 break
69 new_file.write(read_bytes)
70
71 - def put_file(self, filename, path):
72 """Upload a file with PUT."""
73 path = 'content/' + path.lstrip("/")
74 url = self.get_url_from_path(path, None)
75 return self._upload_file(filename, url)
76
77 - def _upload_file(self, filename, url):
78 """Stream a file as an upload."""
79 auth_header = self.auth.get_auth_headers(url, None, 'PUT')
80 parsed_url = urlparse.urlparse(url)
81 size = os.path.getsize(filename)
82 content_type = mimetypes.guess_type(filename)[0]
83 connection = httplib.HTTPSConnection(parsed_url.hostname,
84 parsed_url.port)
85 connection.putrequest('PUT', parsed_url.path)
86 connection.putheader('User-Agent', 'restful-u1')
87 connection.putheader('Content-Length', size)
88 connection.putheader('Connection', 'close')
89 connection.putheader('Content-Type',
90 content_type or 'application/octet-stream')
91 connection.putheader('Authorization', auth_header['Authorization'])
92 connection.endheaders()
93 transferred = 0
94 with open(filename, 'rb') as upload_file:
95 while True:
96 bytes_read = upload_file.read(4096)
97 if not bytes_read:
98 break
99 transferred += len(bytes_read)
100 connection.send(bytes_read)
101 connection.send('0\r\n\r\n')
102 resp = connection.getresponse()
103 if transferred != size:
104 raise Exception("Transferred bytes do not equal file size.")
105 if resp.status < 200 or resp.status > 299:
106 resp.read()
107 raise Exception(resp.status, resp.reason)
108 else:
109 return json.loads(resp.read())
110