Browse code

- New feature - allow "get" to stdout

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
Showing 2 changed files
... ...
@@ -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())