git-svn-id: https://s3tools.svn.sourceforge.net/svnroot/s3tools/s3cmd/trunk@80 830e0280-6d2a-0410-9c65-932aecc39d9d
Michal Ludvig authored on 2007/02/19 11:33:20... | ... |
@@ -3,6 +3,7 @@ |
3 | 3 |
## http://www.logix.cz/michal |
4 | 4 |
## License: GPL Version 2 |
5 | 5 |
|
6 |
+import sys |
|
6 | 7 |
import os, os.path |
7 | 8 |
import base64 |
8 | 9 |
import md5 |
... | ... |
@@ -124,16 +125,18 @@ class S3(object): |
124 | 124 |
response["size"] = size |
125 | 125 |
return response |
126 | 126 |
|
127 |
- def object_get(self, filename, bucket, object): |
|
127 |
+ def object_get_file(self, bucket, object, filename): |
|
128 | 128 |
try: |
129 |
- file = open(filename, "w") |
|
129 |
+ stream = open(filename, "w") |
|
130 | 130 |
except IOError, e: |
131 | 131 |
raise ParameterError("%s: %s" % (filename, e.strerror)) |
132 |
+ return self.object_get_stream(bucket, object, stream) |
|
133 |
+ |
|
134 |
+ def object_get_stream(self, bucket, object, stream): |
|
132 | 135 |
request = self.create_request("OBJECT_GET", bucket = bucket, object = object) |
133 |
- response = self.recv_file(request, file) |
|
134 |
- response["size"] = int(response["headers"]["content-length"]) |
|
136 |
+ response = self.recv_file(request, stream) |
|
135 | 137 |
return response |
136 |
- |
|
138 |
+ |
|
137 | 139 |
def object_delete(self, bucket, object): |
138 | 140 |
request = self.create_request("OBJECT_DELETE", bucket = bucket, object = object) |
139 | 141 |
response = self.send_request(request) |
... | ... |
@@ -144,10 +147,13 @@ class S3(object): |
144 | 144 |
raise ValueError("Expected URI type 's3', got '%s'" % uri.type) |
145 | 145 |
return self.object_put(filename, uri.bucket(), uri.object()) |
146 | 146 |
|
147 |
- def object_get_uri(self, filename, uri): |
|
147 |
+ def object_get_uri(self, uri, filename): |
|
148 | 148 |
if uri.type != "s3": |
149 | 149 |
raise ValueError("Expected URI type 's3', got '%s'" % uri.type) |
150 |
- return self.object_get(filename, uri.bucket(), uri.object()) |
|
150 |
+ if filename == "-": |
|
151 |
+ return self.object_get_stream(uri.bucket(), uri.object(), sys.stdout) |
|
152 |
+ else: |
|
153 |
+ return self.object_get_file(uri.bucket(), uri.object(), filename) |
|
151 | 154 |
|
152 | 155 |
def object_delete_uri(self, uri): |
153 | 156 |
if uri.type != "s3": |
... | ... |
@@ -232,9 +238,9 @@ class S3(object): |
232 | 232 |
raise S3Error(response) |
233 | 233 |
return response |
234 | 234 |
|
235 |
- def recv_file(self, request, file): |
|
235 |
+ def recv_file(self, request, stream): |
|
236 | 236 |
method_string, resource, headers = request |
237 |
- info("Receiving file '%s', please wait..." % file.name) |
|
237 |
+ info("Receiving file '%s', please wait..." % stream.name) |
|
238 | 238 |
conn = httplib.HTTPConnection(self.config.host) |
239 | 239 |
conn.connect() |
240 | 240 |
conn.putrequest(method_string, resource) |
... | ... |
@@ -251,26 +257,30 @@ class S3(object): |
251 | 251 |
|
252 | 252 |
md5_hash = md5.new() |
253 | 253 |
size_left = size_total = int(response["headers"]["content-length"]) |
254 |
- while (size_left > 0): |
|
254 |
+ size_recvd = 0 |
|
255 |
+ while (size_recvd < size_total): |
|
255 | 256 |
this_chunk = size_left > self.config.recv_chunk and self.config.recv_chunk or size_left |
256 | 257 |
debug("ReceiveFile: Receiving up to %d bytes from the server" % this_chunk) |
257 | 258 |
data = http_response.read(this_chunk) |
258 |
- debug("ReceiveFile: Writing %d bytes to file '%s'" % (len(data), file.name)) |
|
259 |
- file.write(data) |
|
259 |
+ debug("ReceiveFile: Writing %d bytes to file '%s'" % (len(data), stream.name)) |
|
260 |
+ stream.write(data) |
|
260 | 261 |
md5_hash.update(data) |
261 |
- size_left -= len(data) |
|
262 |
+ size_recvd += len(data) |
|
262 | 263 |
info("Received %d bytes (%d %% of %d)" % ( |
263 |
- (size_total - size_left), |
|
264 |
- (size_total - size_left) * 100 / size_total, |
|
264 |
+ size_recvd, |
|
265 |
+ size_recvd * 100 / size_total, |
|
265 | 266 |
size_total)) |
266 | 267 |
conn.close() |
267 | 268 |
response["md5"] = md5_hash.hexdigest() |
268 | 269 |
response["md5match"] = response["headers"]["etag"].find(response["md5"]) >= 0 |
270 |
+ response["size"] = size_recvd |
|
271 |
+ if response["size"] != long(response["headers"]["content-length"]): |
|
272 |
+ warning("Reported size (%s) does not match received size (%s)" % ( |
|
273 |
+ response["headers"]["content-length"], response["size"])) |
|
269 | 274 |
debug("ReceiveFile: Computed MD5 = %s" % response["md5"]) |
270 | 275 |
if not response["md5match"]: |
271 | 276 |
warning("MD5 signatures do not match: computed=%s, received=%s" % ( |
272 | 277 |
response["md5"], response["headers"]["etag"])) |
273 |
- |
|
274 | 278 |
return response |
275 | 279 |
|
276 | 280 |
def sign_headers(self, method, resource, headers): |
... | ... |
@@ -144,9 +144,10 @@ def cmd_object_get(args): |
144 | 144 |
destination += ("/" + uri.object()) |
145 | 145 |
if not Config().force and os.path.exists(destination): |
146 | 146 |
raise ParameterError("File %s already exists. Use --force to overwrite it" % destination) |
147 |
- response = s3.object_get_uri(destination, uri) |
|
148 |
- output("Object %s saved as '%s' (%d bytes)" % |
|
149 |
- (uri, destination, response["size"])) |
|
147 |
+ response = s3.object_get_uri(uri, destination) |
|
148 |
+ if destination != "-": |
|
149 |
+ output("Object %s saved as '%s' (%d bytes)" % |
|
150 |
+ (uri, destination, response["size"])) |
|
150 | 151 |
|
151 | 152 |
def cmd_object_del(args): |
152 | 153 |
s3 = S3(Config()) |