@@ -82,6 +82,10 @@ def xml_to_dict(data):
8282 """V5使用xml格式,将response中的xml转换为dict"""
8383 root = xml .etree .ElementTree .fromstring (data )
8484 xmldict = Xml2Dict (root )
85+ xmlstr = str (xmldict )
86+ xmlstr = xmlstr .replace ("{http://www.qcloud.com/document/product/436/7751}" , "" )
87+ xmlstr = xmlstr .replace ("{http://www.w3.org/2001/XMLSchema-instance}" , "" )
88+ xmldict = eval (xmlstr )
8589 return xmldict
8690
8791
@@ -147,13 +151,11 @@ def __init__(self, conf, retry=1, session=None):
147151 else :
148152 self ._session = session
149153
150- def get_auth (self , Method , Bucket , Key = None , ** kwargs ):
154+ def get_auth (self , Method , Bucket , Key = None , Expired = 10000 , headers = {}, params = {} ):
151155 """获取签名"""
152- headers = mapped (kwargs )
153- # TODO(tiedu) 检查header的参数合法性
154156 url = self ._conf .uri (bucket = Bucket , path = Key )
155- r = Request (Method , url )
156- auth = CosS3Auth (self ._conf ._access_id , self ._conf ._access_key )
157+ r = Request (Method , url , headers = headers , params = params )
158+ auth = CosS3Auth (self ._conf ._access_id , self ._conf ._access_key , Expired )
157159 return auth (r ).headers ['Authorization' ]
158160
159161 def send_request (self , method , url , timeout = 30 , ** kwargs ):
@@ -239,10 +241,10 @@ def get_object(self, Bucket, Key, **kwargs):
239241 response [k ] = rt .headers [k ]
240242 return response
241243
242- def get_presigned_download_url (self , Bucket , Key ):
244+ def get_presigned_download_url (self , Bucket , Key , Expired = 10000 ):
243245 """生成预签名的下载url"""
244246 url = self ._conf .uri (bucket = Bucket , path = Key )
245- sign = self .get_auth (Method = 'GET' , Bucket = Bucket , Key = Key )
247+ sign = self .get_auth (Method = 'GET' , Bucket = Bucket , Key = Key , Expired = 10000 )
246248 url = url + '?sign=' + urllib .quote (sign )
247249 return url
248250
@@ -353,11 +355,8 @@ def complete_multipart_upload(self, Bucket, Key, UploadId, MultipartUpload={}, *
353355 data = dict_to_xml (MultipartUpload ),
354356 timeout = 1200 , # 分片上传大文件的时间比较长,设置为20min
355357 headers = headers )
356- response = dict ()
357358 data = xml_to_dict (rt .text )
358- for key in data .keys ():
359- response [key [key .find ('}' )+ 1 :]] = data [key ]
360- return response
359+ return data
361360
362361 def abort_multipart_upload (self , Bucket , Key , UploadId , ** kwargs ):
363362 """放弃一个已经存在的分片上传任务,删除所有已经存在的分片"""
@@ -385,18 +384,45 @@ def list_parts(self, Bucket, Key, UploadId, **kwargs):
385384 url = url ,
386385 auth = CosS3Auth (self ._conf ._access_id , self ._conf ._access_key ),
387386 headers = headers )
387+ data = xml_to_dict (rt .text )
388+ if 'Part' in data .keys () and isinstance (data ['Part' ], dict ): # 只有一个part,将dict转为list,保持一致
389+ lst = []
390+ lst .append (data ['Part' ])
391+ data ['Part' ] = lst
392+ return data
393+
394+ def put_object_acl (self , Bucket , Key , ** kwargs ):
395+ """设置object ACL"""
396+ headers = mapped (kwargs )
397+ url = self ._conf .uri (bucket = Bucket , path = Key + "?acl" )
398+ logger .info ("put object acl, url=:{url} ,headers=:{headers}" .format (
399+ url = url ,
400+ headers = headers ))
401+ rt = self .send_request (
402+ method = 'PUT' ,
403+ url = url ,
404+ auth = CosS3Auth (self ._conf ._access_id , self ._conf ._access_key ),
405+ headers = headers )
406+ return None
388407
408+ def get_object_acl (self , Bucket , Key , ** kwargs ):
409+ """获取object ACL"""
410+ headers = mapped (kwargs )
411+ url = self ._conf .uri (bucket = Bucket , path = Key + "?acl" )
412+ logger .info ("get object acl, url=:{url} ,headers=:{headers}" .format (
413+ url = url ,
414+ headers = headers ))
415+ rt = self .send_request (
416+ method = 'GET' ,
417+ url = url ,
418+ auth = CosS3Auth (self ._conf ._access_id , self ._conf ._access_key ),
419+ headers = headers )
389420 data = xml_to_dict (rt .text )
390- if 'Part' in data .keys ():
391- if isinstance (data ['Part' ], list ):
392- return data
393- else : # 只有一个part,将dict转为list,保持一致
394- lst = []
395- lst .append (data ['Part' ])
396- data ['Part' ] = lst
397- return data
398- else :
399- return data
421+ if data ['AccessControlList' ] is not None and isinstance (data ['AccessControlList' ]['Grant' ], dict ):
422+ lst = []
423+ lst .append (data ['AccessControlList' ]['Grant' ])
424+ data ['AccessControlList' ]['Grant' ] = lst
425+ return data
400426
401427 # s3 bucket interface begin
402428 def create_bucket (self , Bucket , ** kwargs ):
@@ -447,16 +473,58 @@ def list_objects(self, Bucket, Delimiter="", Marker="", MaxKeys=1000, Prefix="",
447473 auth = CosS3Auth (self ._conf ._access_id , self ._conf ._access_key ))
448474
449475 data = xml_to_dict (rt .text )
450- if 'Contents' in data .keys ():
451- if isinstance (data ['Contents' ], list ):
452- return data
453- else : # 只有一个Contents,将dict转为list,保持一致
476+ if 'Contents' in data .keys () and isinstance (data ['Contents' ], dict ): # 只有一个Contents,将dict转为list,保持一致
454477 lst = []
455478 lst .append (data ['Contents' ])
456479 data ['Contents' ] = lst
457- return data
458- else :
459- return data
480+ return data
481+
482+ def head_bucket (self , Bucket , ** kwargs ):
483+ """获取bucket信息"""
484+ headers = mapped (kwargs )
485+ url = self ._conf .uri (bucket = Bucket )
486+ logger .info ("head bucket, url=:{url} ,headers=:{headers}" .format (
487+ url = url ,
488+ headers = headers ))
489+ rt = self .send_request (
490+ method = 'HEAD' ,
491+ url = url ,
492+ auth = CosS3Auth (self ._conf ._access_id , self ._conf ._access_key ),
493+ headers = headers )
494+ return None
495+
496+ def put_bucket_acl (self , Bucket , ** kwargs ):
497+ """设置bucket ACL"""
498+ headers = mapped (kwargs )
499+ url = self ._conf .uri (bucket = Bucket , path = "?acl" )
500+ logger .info ("put bucket acl, url=:{url} ,headers=:{headers}" .format (
501+ url = url ,
502+ headers = headers ))
503+ rt = self .send_request (
504+ method = 'PUT' ,
505+ url = url ,
506+ auth = CosS3Auth (self ._conf ._access_id , self ._conf ._access_key ),
507+ headers = headers )
508+ return None
509+
510+ def get_bucket_acl (self , Bucket , ** kwargs ):
511+ """获取bucket ACL"""
512+ headers = mapped (kwargs )
513+ url = self ._conf .uri (bucket = Bucket , path = "?acl" )
514+ logger .info ("get bucket acl, url=:{url} ,headers=:{headers}" .format (
515+ url = url ,
516+ headers = headers ))
517+ rt = self .send_request (
518+ method = 'GET' ,
519+ url = url ,
520+ auth = CosS3Auth (self ._conf ._access_id , self ._conf ._access_key ),
521+ headers = headers )
522+ data = xml_to_dict (rt .text )
523+ if data ['AccessControlList' ] is not None and isinstance (data ['AccessControlList' ]['Grant' ], dict ):
524+ lst = []
525+ lst .append (data ['AccessControlList' ]['Grant' ])
526+ data ['AccessControlList' ]['Grant' ] = lst
527+ return data
460528
461529 # service interface begin
462530 def list_buckets (self , ** kwargs ):
@@ -470,6 +538,10 @@ def list_buckets(self, **kwargs):
470538 auth = CosS3Auth (self ._conf ._access_id , self ._conf ._access_key ),
471539 )
472540 data = xml_to_dict (rt .text )
541+ if data ['Buckets' ] is not None and isinstance (data ['Buckets' ]['Bucket' ], dict ):
542+ lst = []
543+ lst .append (data ['Buckets' ]['Bucket' ])
544+ data ['Buckets' ]['Bucket' ] = lst
473545 return data
474546
475547if __name__ == "__main__" :
0 commit comments