86 lines
3.1 KiB
Python
86 lines
3.1 KiB
Python
from oss2 import SizedFileAdapter, determine_part_size
|
||
from oss2.models import PartInfo
|
||
import oss2
|
||
from aliyunsdkcore.client import AcsClient
|
||
from aliyunsdkcdn.request.v20180510 import RefreshObjectCachesRequest
|
||
from ops.mlog import log
|
||
import os
|
||
import json
|
||
import hashlib
|
||
import base64
|
||
|
||
"""
|
||
pip install oss2 aliyun-python-sdk-core aliyun-python-sdk-cdn
|
||
|
||
阿里云api通用类
|
||
"""
|
||
|
||
|
||
class AliApi(object):
|
||
def __init__(self, access_key_id=None, access_key_secret=None):
|
||
self.access_key_id = access_key_id or os.environ.get('ALI_ACCESS_KEY_ID')
|
||
self.access_key_secret = access_key_secret or os.environ.get('ALI_ACCESS_KEY_SECRET')
|
||
|
||
def calculate_file_md5(self, file_name, block_size=64 * 1024):
|
||
"""计算文件的MD5
|
||
:param file_name: 文件名
|
||
:param block_size: 计算MD5的数据块大小,默认64KB
|
||
:return 文件内容的MD5值
|
||
"""
|
||
with open(file_name, 'rb') as f:
|
||
md5 = hashlib.md5()
|
||
while True:
|
||
data = f.read(block_size)
|
||
if not data:
|
||
break
|
||
md5.update(data)
|
||
|
||
return base64.b64encode(md5.digest()).decode()
|
||
|
||
def oss_upload(self, endpoint, bucket_name, file, key):
|
||
auth = oss2.Auth(self.access_key_id, self.access_key_secret)
|
||
bucket = oss2.Bucket(auth, endpoint, bucket_name)
|
||
|
||
total_size = os.path.getsize(file)
|
||
# determine_part_size方法用来确定分片大小。
|
||
part_size = determine_part_size(total_size, preferred_size=100 * 1024)
|
||
|
||
# 初始化分片。
|
||
upload_id = bucket.init_multipart_upload(key).upload_id
|
||
parts = []
|
||
|
||
try:
|
||
# 逐个上传分片。
|
||
with open(file, 'rb') as fileobj:
|
||
part_number = 1
|
||
offset = 0
|
||
while offset < total_size:
|
||
num_to_upload = min(part_size, total_size - offset)
|
||
# SizedFileAdapter(fileobj, size)方法会生成一个新的文件对象,重新计算起始追加位置。
|
||
result = bucket.upload_part(key, upload_id, part_number, SizedFileAdapter(fileobj, num_to_upload),
|
||
headers={'Content-MD5': self.calculate_file_md5(file)})
|
||
parts.append(PartInfo(part_number, result.etag))
|
||
|
||
offset += num_to_upload
|
||
part_number += 1
|
||
|
||
# 完成分片上传。
|
||
bucket.complete_multipart_upload(key, upload_id, parts)
|
||
log.info("{0} upload complete".format(file))
|
||
except:
|
||
log.info("{0} upload failed".format(file))
|
||
|
||
def cdn_refresh_dir(self, refresh_url, region='cn-shanghai'):
|
||
client = AcsClient(self.access_key_id, self.access_key_secret, region)
|
||
|
||
request = RefreshObjectCachesRequest.RefreshObjectCachesRequest()
|
||
request.set_ObjectPath(refresh_url)
|
||
if refresh_url.endswith('/'):
|
||
request.set_ObjectType('Directory')
|
||
else:
|
||
request.set_ObjectType('File')
|
||
response = client.do_action_with_exception(request)
|
||
rel = json.loads(response.decode('utf-8'))
|
||
return rel
|
||
|