Skip to content

Commit 17e406a

Browse files
committed
Add EnableMD5 for put object
1 parent 6ee2c07 commit 17e406a

File tree

3 files changed

+45
-1
lines changed

3 files changed

+45
-1
lines changed

qcloud_cos/cos_client.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -190,12 +190,13 @@ def send_request(self, method, url, timeout=30, **kwargs):
190190
return None
191191

192192
# s3 object interface begin
193-
def put_object(self, Bucket, Body, Key, **kwargs):
193+
def put_object(self, Bucket, Body, Key, EnableMD5=False, **kwargs):
194194
"""单文件上传接口,适用于小文件,最大不得超过5GB
195195
196196
:param Bucket(string): 存储桶名称.
197197
:param Body(file|string): 上传的文件内容,类型为文件流或字节流.
198198
:param Key(string): COS路径.
199+
:param EnableMD5(bool): 是否需要SDK计算Content-MD5,打开此开关会增加上传耗时.
199200
:kwargs(dict): 设置上传的headers.
200201
:return(dict): 上传成功返回的结果,包含ETag等信息.
201202
@@ -223,6 +224,10 @@ def put_object(self, Bucket, Body, Key, **kwargs):
223224
url=url,
224225
headers=headers))
225226
Body = deal_with_empty_file_stream(Body)
227+
if EnableMD5:
228+
md5_str = get_content_md5(Body)
229+
if md5_str:
230+
headers['Content-MD5'] = md5_str
226231
rt = self.send_request(
227232
method='PUT',
228233
url=url,

qcloud_cos/cos_comm.py

+16
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,21 @@ def get_md5(data):
6969
return MD5
7070

7171

72+
def get_content_md5(body):
73+
body_type = type(body)
74+
if body_type == str:
75+
return get_md5(body)
76+
elif body_type == file:
77+
if hasattr(body, 'tell') and hasattr(body, 'seek') and hasattr(body, 'read'):
78+
file_position = body.tell() # 记录文件当前位置
79+
md5_str = get_md5(body.read())
80+
body.seek(file_position) # 恢复初始的文件位置
81+
return md5_str
82+
else:
83+
raise CosClientError('can not get md5 digest for file without necessary attrs, including tell, seek and read')
84+
return None
85+
86+
7287
def dict_to_xml(data):
7388
"""V5使用xml格式,将输入的dict转换为xml"""
7489
doc = xml.dom.minidom.Document()
@@ -105,6 +120,7 @@ def xml_to_dict(data, origin_str="", replace_str=""):
105120
xmldict = Xml2Dict(root)
106121
xmlstr = str(xmldict)
107122
xmlstr = xmlstr.replace("{http://www.qcloud.com/document/product/436/7751}", "")
123+
xmlstr = xmlstr.replace("{https://cloud.tencent.com/document/product/436}", "")
108124
xmlstr = xmlstr.replace("{http://doc.s3.amazonaws.com/2006-03-01}", "")
109125
xmlstr = xmlstr.replace("{http://www.w3.org/2001/XMLSchema-instance}", "")
110126
if origin_str:

ut/test.py

+23
Original file line numberDiff line numberDiff line change
@@ -645,12 +645,35 @@ def test_put_get_bucket_logging():
645645
response = logging_client.get_bucket_logging(
646646
Bucket=logging_bucket
647647
)
648+
print response
648649
assert response['LoggingEnabled']['TargetBucket'] == logging_bucket
649650
assert response['LoggingEnabled']['TargetPrefix'] == 'test'
650651

651652

653+
def test_put_object_enable_md5():
654+
"""上传文件,SDK计算content-md5头部"""
655+
file_size = 10
656+
file_name = 'test_object_sdk_caculate_md5.file'
657+
gen_file(file_name, 10)
658+
with open(file_name, 'rb') as f:
659+
etag = get_raw_md5(f.read())
660+
with open(file_name, 'rb') as fp:
661+
put_response = client.put_object(
662+
Bucket=test_bucket,
663+
Body=fp,
664+
Key=file_name,
665+
EnableMD5=True,
666+
CacheControl='no-cache',
667+
ContentDisposition='download.txt'
668+
)
669+
assert etag == put_response['Etag']
670+
if os.path.exists(file_name):
671+
os.remove(file_name)
672+
673+
652674
if __name__ == "__main__":
653675
setUp()
676+
test_put_object_enable_md5()
654677
test_upload_with_server_side_encryption()
655678
test_upload_empty_file()
656679
test_put_get_delete_object_10MB()

0 commit comments

Comments
 (0)