• R/O
  • HTTP
  • SSH
  • HTTPS

提交

Frequently used words (click to add to your profile)

javaandroidc++linuxc#objective-ccocoa誰得qtrubypythongamewindowsbathyscaphephpguic翻訳omegattwitterframeworktestbtronarduinovb.net計画中(planning stage)directxpreviewerゲームエンジンdom

winazurestorageのフォーク


Commit MetaInfo

修订版1b59f56c5e7c7a724b9e95e43cabef8236dd537b (tree)
时间2011-09-13 06:41:01
作者Steve Marx <Steve.Marx@micr...>
CommiterSteve Marx

Log Message

adding blob metadata operations and 'list blobs'

更改概述

差异

--- a/winazurestorage.py
+++ b/winazurestorage.py
@@ -15,6 +15,7 @@ import os
1515 from xml.dom import minidom #TODO: Use a faster way of processing XML
1616 import re
1717 from urllib2 import Request, urlopen, URLError
18+from urllib import urlencode
1819 from urlparse import urlsplit
1920 from datetime import datetime, timedelta
2021
@@ -310,11 +311,12 @@ class BlobStorage(Storage):
310311
311312 dom.unlink() #Docs say to do this to force GC. Ugh.
312313
313- def put_blob(self, container_name, blob_name, data, content_type = None):
314+ def put_blob(self, container_name, blob_name, data, content_type = "", metadata = {}):
314315 req = RequestWithMethod("PUT", "%s/%s/%s" % (self.get_base_url(), container_name, blob_name), data=data)
315316 req.add_header("Content-Length", "%d" % len(data))
316- if content_type is not None: req.add_header("Content-Type", content_type)
317- else: req.add_header("Content-Type", "")
317+ for key, value in metadata.items():
318+ req.add_header("x-ms-meta-%s" % key, value)
319+ req.add_header("Content-Type", content_type)
318320 self._credentials.sign_request(req)
319321 try:
320322 response = urlopen(req)
@@ -322,11 +324,54 @@ class BlobStorage(Storage):
322324 except URLError, e:
323325 return e.code
324326
327+ def delete_blob(self, container_name, blob_name):
328+ req = RequestWithMethod("DELETE", "%s/%s/%s" % (self.get_base_url(), container_name, blob_name))
329+ self._credentials.sign_request(req)
330+ urlopen(req)
331+
325332 def get_blob(self, container_name, blob_name):
326333 req = Request("%s/%s/%s" % (self.get_base_url(), container_name, blob_name))
327334 self._credentials.sign_request(req)
328335 return urlopen(req).read()
329336
337+ def get_blob_with_metadata(self, container_name, blob_name):
338+ req = Request("%s/%s/%s" % (self.get_base_url(), container_name, blob_name))
339+ self._credentials.sign_request(req)
340+ response = urlopen(req)
341+ metadata = {}
342+ for key, value in response.info().items():
343+ if key.startswith('x-ms-meta-'):
344+ metadata[key[len('x-ms-meta-'):]] = value
345+ return metadata, response.read()
346+
347+ def blob_exists(self, container_name, blob_name):
348+ req = RequestWithMethod("HEAD", "%s/%s/%s" % (self.get_base_url(), container_name, blob_name))
349+ self._credentials.sign_request(req)
350+ try:
351+ urlopen(req)
352+ return True
353+ except:
354+ return False
355+
356+ def list_blobs(self, container_name, blob_prefix=None):
357+ marker = None
358+ while True:
359+ url = "%s/%s?restype=container&comp=list" % (self.get_base_url(), container_name)
360+ if not blob_prefix is None: url += "&%s" % urlencode({"prefix": blob_prefix})
361+ if not marker is None: url += "&marker=%s" % marker
362+ req = Request(url)
363+ self._credentials.sign_request(req)
364+ dom = minidom.parseString(urlopen(req).read())
365+ blobs = dom.getElementsByTagName("Blob")
366+ for blob in blobs:
367+ blob_name = blob.getElementsByTagName("Name")[0].firstChild.data
368+ etag = blob.getElementsByTagName("Etag")[0].firstChild.data
369+ last_modified = time.strptime(blob.getElementsByTagName("LastModified")[0].firstChild.data, TIME_FORMAT)
370+ yield (blob_name, etag, last_modified)
371+ try: marker = dom.getElementsByTagName("NextMarker")[0].firstChild.data
372+ except: marker = None
373+ if marker is None: break
374+
330375 def main():
331376 pass
332377