融合接口
功能說明
分片(pian)上(shang)傳(chuan)步驟(zou)較多,包(bao)括(kuo)初始化、文件切段(duan)、各個分片(pian)上(shang)傳(chuan)、完(wan)成上(shang)傳(chuan)。為了簡化分片(pian)上(shang)傳(chuan),SDK提供了方(fang)便的融合接口(kou)用于上(shang)傳(chuan)文件,用戶(hu)不需要關(guan)心(xin)文件的大小,SDK會自動對大文件使用分片(pian)上(shang)傳(chuan)。
代碼示例
import botocore.config
import botocore.session
import s3transfer.manager
import datetime
?
class TransferDemo(object):
def __init__(self):
config = botocore.config.Config(
signature_version='s3v4', # 簽名版本,s3 or s3v4
)
?
self.bucket = '<your-bucket-name>'
session = botocore.session.get_session()
self.s3_client = session.create_client(
's3',
aws_access_key_id='<your-access-key>',
aws_secret_access_key='<your-secret-key>',
endpoint_url='<your-endpoint>',
config=config)
?
MB = 1024 * 1024
transConfig = s3transfer.manager.TransferConfig(
multipart_threshold=5 * MB, # 大于該值使用分片上傳
multipart_chunksize=5 * MB, # 分片大小
max_request_concurrency=2,
)
?
# 設置帶寬,不填表示不限制
# transConfig.max_bandwidth = 1 * MB
?
self.transfer = s3transfer.manager.TransferManager(self.s3_client, transConfig)
?
def upload(self):
print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'), "upload start")
key = '<your-object-key>'
# 擴展配置,可以設置ContentType和ACL
extraArgs = {'ContentType': 'text/plain', 'ACL': 'public-read'}
with open('<file-path>', 'rb') as f:
future = self.transfer.upload(f, self.bucket, key, extra_args=extraArgs)
future.result()
請求參數
| 參數 | 類型 | 說明 |
|---|
| bucket | string | 桶名 |
| key | string | 對象名 |
| fileobj | fileobj | 打開的文件對象 |
| extra_args | dict | 擴展配置,可以設置ContentType和ACL;ACL取值private | public-read | public-read-write |
TransferConfig參數(shu),
| 參數 | 類型 | 說明 |
|---|
| multipart_threshold | int | 大于該值使用分片上傳 |
| multipart_chunksize | int | 分片大小,默認5MB |
| max_request_concurrency | int | 上傳分片并發數 |
關于Content-Type的配置
Content-Type用于標識文件的資源類型,比如image/png, image/jpg 是圖片類型,video/mpeg, video/mp4是視頻類型,text/plain, text/html是文本類型, 瀏覽器針對不同的Content-Type會有不同的操作,比如圖片類型可以預覽,視頻類型可以播放,文本類型可以直接打開。application/octet-stream類(lei)型會直接打開下載窗(chuang)口(kou)。
有些用戶反饋圖片和視頻無法預覽的問題,主要就是Content-Type沒有正確設置導致的;Content-Type參數需要用戶主動設置,默認是application/octet-stream。在python sdk中,可以根據對象key值(zhi)后綴擴(kuo)展名來決定文(wen)件的Content-Type,參考代(dai)碼如(ru)下:
import mimetypes
?
def mime_type(key):
mt = mimetypes.guess_type(key)[0]
if mt == None :
return ""
return mt
初始化分片上傳任務
功能說明
您可以使用(yong)create_multipart_upload接口創建(jian)上傳(chuan)任(ren)務(wu)。
代碼示例
# create_multipart_upload
resp = self.s3_client.create_multipart_upload(
Bucket='<your-bucket-name>',
Key='<your-object-key>'
)
upload_id = resp['UploadId']
print('create_multipart_upload success upload_id: %s' %upload_id)
請求參數
| 參數 | 類型 | 說明 | 是否必要 |
|---|
| Bucket | string | 桶名稱 | 是 |
| Key | string | 對象key | 是 |
返回結果
| 參數 | 類型 | 說明 |
|---|
| UploadId | string | 分片上傳任務的id |
上傳分片
功能說明
初(chu)始(shi)化(hua)分(fen)(fen)(fen)片(pian)上(shang)(shang)(shang)傳(chuan)(chuan)任務后,指定(ding)分(fen)(fen)(fen)片(pian)上(shang)(shang)(shang)傳(chuan)(chuan)任務的(de)id可(ke)以(yi)上(shang)(shang)(shang)傳(chuan)(chuan)分(fen)(fen)(fen)片(pian)數據(ju),可(ke)以(yi)將(jiang)大文件分(fen)(fen)(fen)割成分(fen)(fen)(fen)片(pian)后上(shang)(shang)(shang)傳(chuan)(chuan),除了(le)最后一個(ge)(ge)分(fen)(fen)(fen)片(pian),每(mei)個(ge)(ge)分(fen)(fen)(fen)片(pian)的(de)數據(ju)大小為5MB~5GB,每(mei)個(ge)(ge)分(fen)(fen)(fen)片(pian)上(shang)(shang)(shang)傳(chuan)(chuan)任務最多上(shang)(shang)(shang)傳(chuan)(chuan)10000個(ge)(ge)分(fen)(fen)(fen)片(pian)。您可(ke)以(yi)使用upload_part上(shang)(shang)(shang)傳(chuan)(chuan)分(fen)(fen)(fen)片(pian)。
代碼示例
def multipart_upload(self):
bucket = '<your-bucket-name>'
key = '<your-object-key>'
local_path = '<file-path>'
parts = [] # part list uploaded by client
part_size = 5 * 1024 * 1024
# create_multipart_upload
resp = self.s3_client.create_multipart_upload(
Bucket=bucket,
Key=key
)
upload_id = resp['UploadId']
print('create_multipart_upload success upload_id: %s' %upload_id)
# upload_part
with open(local_path, 'rb') as f:
s = f.read(part_size)
part_num = 1
while s:
file_chunk = io.BytesIO(s)
resp = self.s3_client.upload_part(
Bucket=bucket,
Key=key,
Body=file_chunk,
UploadId=upload_id,
PartNumber=part_num,
)
print('upload part %d success' %part_num)
part = {
'ETag': resp['ETag'],
'PartNumber': part_num
}
parts.append(part)
s = f.read(part_size)
part_num += 1
# complete_multipart_upload
resp = self.s3_client.complete_multipart_upload(
Bucket=bucket,
Key=key,
UploadId=upload_id,
MultipartUpload={
'Parts': parts
},
)
print('complete_multipart_upload success upload_id: %s' %upload_id)
請求參數
| 參數 | 類型 | 說明 | 是否必要 |
|---|
| Bucket | string | 桶名稱 | 是 |
| Key | string | 對象key | 是 |
| Body | bytes|file | 對象的數據 | 是 |
| PartNumber | int | 當前分片號碼 | 是 |
| UploadId | string | 通過創建上傳任務接口獲取到的任務Id | 是 |
返回結果
| 參數 | 類型 | 說明 |
|---|
| ETag | string | 本次上傳分片對應的Entity Tag |
合并分片
功能說明
合(he)并指(zhi)定(ding)分(fen)片(pian)上傳任務id對(dui)應任務中已上傳的對(dui)象分(fen)片(pian),使之成為一個完整(zheng)的文件。您(nin)可以使用complete_multipart_upload接口合(he)并分(fen)片(pian)。
代碼示例
# complete_multipart_upload
resp = self.s3_client.complete_multipart_upload(
Bucket='<your-bucket-name>',
Key='<your-object-key>',
UploadId=upload_id,
MultipartUpload={
'Parts': parts
},
)
print('complete_multipart_upload success upload_id: %s' %upload_id)
請求參數
| 參數 | 類型 | 說明 | 是否必要 |
|---|
| Bucket | string | 桶名稱 | 是 |
| Key | string | 對象key | 是 |
| MultipartUpload | MultipartUpload | 包含了每個已上傳的分片的ETag和PartNUmber等信息 | 是 |
| UploadId | string | 通過創建上傳任務接口獲取到的任務Id | 是 |
返回結果
| 參數 | 類型 | 說明 |
|---|
| ETag | string | 本次上傳對象后對應的Entity Tag |
列舉分片上傳任務
功能說明
您可以使(shi)用(yong)list_multipart_uploads獲(huo)取未完成(cheng)的上傳任務(wu)。
代碼示例
def list_multipart_uploads(self):
print('list_multipart_uploads')
prefix = '<your-object-key>'
resp = self.s3_client.list_multipart_uploads(
Bucket='<your-bucket-name>',
Prefix=prefix,
MaxUploads=50,
)
for task in resp['Uploads']:
print('key: %s, id: %s' %(task['Key'], task['UploadId']))
請求參數
| 參數 | 類型 | 說明 | 是否必要 |
|---|
| Bucket | string | 桶名稱 | 是 |
| MaxUploads | int | 用于指定獲取任務的最大數量(1-1000) | 否 |
| Prefix | string | 指定上傳對象key的前綴 | 否 |
返回結果
| 參數 | 類型 | 說明 |
|---|
| Uploads | Uploads | 包含了零個或多個已初始化的上傳分片信息的數組。數組中的每一項包含了分片初始化時間、分片上傳操作發起者、對象key、對象擁有者、存儲類型和UploadId等信息 |
列舉已上傳的分片
功能說明
您可(ke)以使用list_parts獲(huo)取一(yi)個未完成的(de)上(shang)傳任務中已完成上(shang)傳的(de)分片信(xin)息。
代碼示例
def list_parts(self):
print('list_parts')
key = '<your-object-key>'
resp = self.s3_client.list_parts(
Bucket='<your-bucket-name>',
Key=key,
UploadId='<upload id>',
)
print(resp)
請求參數
| 參數 | 類型 | 說明 | 是否必要 |
|---|
| Bucket | string | 桶名稱 | 是 |
| Key | string | 對象key | 是 |
| UploadId | string | 指定返回該任務id所屬的分片上傳的分片信息 | 是 |
返回結果
| 參數 | 類型 | 說明 |
|---|
| Parts | Parts | 包含了已上傳分片信息的數組,數組中的每一項包含了該分片的Entity tag、最后修改時間、PartNumber和大小等信息 |
復制分片
功能說明
復(fu)制分(fen)片(pian)(pian)(pian)操(cao)作(zuo)(zuo)可(ke)以從一(yi)個(ge)(ge)已存(cun)在的(de)對(dui)象中拷(kao)(kao)貝指(zhi)定分(fen)片(pian)(pian)(pian)的(de)數據,當(dang)拷(kao)(kao)貝的(de)對(dui)象大(da)小超過5GB,必須使用(yong)復(fu)制分(fen)片(pian)(pian)(pian)操(cao)作(zuo)(zuo)完(wan)成(cheng)對(dui)象的(de)復(fu)制。除(chu)了最(zui)后一(yi)個(ge)(ge)分(fen)片(pian)(pian)(pian)外,每(mei)個(ge)(ge)拷(kao)(kao)貝分(fen)片(pian)(pian)(pian)的(de)大(da)小范圍(wei)是[5MB,5GB]。在一(yi)個(ge)(ge)在拷(kao)(kao)貝大(da)對(dui)象之前(qian),需要使用(yong)初(chu)始化(hua)分(fen)片(pian)(pian)(pian)上(shang)傳(chuan)操(cao)作(zuo)(zuo)獲(huo)取一(yi)個(ge)(ge)upload id,在完(wan)成(cheng)拷(kao)(kao)貝操(cao)作(zuo)(zuo)之后,需要使用(yong)合并分(fen)片(pian)(pian)(pian)操(cao)作(zuo)(zuo)組裝已拷(kao)(kao)貝的(de)分(fen)片(pian)(pian)(pian)成(cheng)為一(yi)個(ge)(ge)對(dui)象。您可(ke)以使用(yong)upload_part_copy復(fu)制一(yi)個(ge)(ge)分(fen)片(pian)(pian)(pian)。
代碼示例
def multipart_copy(self):
bucket = '<dst-bucket-name>'
key = '<dst-object-key>'
source_bucket = '<source-bucket-name>'
source_key = '<source-object-key>'
parts = [] # part list uploaded by client
part_size = 5 * 1024 * 1024
?
# head_object
resp = self.s3_client.head_object(
Bucket=bucket,
Key=source_key
)
print('head_object success length: %s' %resp['ContentLength'])
size = resp['ContentLength']
# create_multipart_upload
resp = self.s3_client.create_multipart_upload(
Bucket=bucket,
Key=key
)
upload_id = resp['UploadId']
print('create_multipart_upload success upload_id: %s' %upload_id)
# upload_part
start = 0
part_num = 1
while start < size:
if start + part_size < size:
end = start + part_size - 1
else:
end = size - 1
resp = self.s3_client.upload_part_copy(
Bucket=bucket,
Key=key,
CopySource={'Bucket': source_bucket, 'Key': source_key},
UploadId=upload_id,
PartNumber=part_num,
CopySourceRange='bytes=%d-%d' %(start, end)
)
print('copy part %d success' %part_num)
part = {
'ETag': resp['CopyPartResult']['ETag'],
'PartNumber': part_num
}
parts.append(part)
start = end + 1
part_num += 1
?
# complete_multipart_upload
resp = self.s3_client.complete_multipart_upload(
Bucket=bucket,
Key=key,
UploadId=upload_id,
MultipartUpload={
'Parts': parts
},
)
print('complete_multipart_upload success upload_id: %s' %upload_id)
請求參數
| 參數 | 類型 | 說明 | 是否必要 |
|---|
| Bucket | string | 桶名稱 | 是 |
| Key | string | 目的對象key | 是 |
| PartNumber | int | 當前分片號碼 | 是 |
| UploadId | string | 通過創建上傳任務接口獲取到的任務Id | 是 |
| CopySource | string | 源對象 | 是 |
| CopySourceRange | string | 指定本次分片拷貝的數據范圍,必須是"bytes=first-last"的格式,例如"bytes=0-9"表示拷貝原對象中前10字節的數據,只有當拷貝的分片大小大于5MB的時候有效 | 否 |
關于CopySource:
| 參數 | 類型 | 說明 | 是否必要 |
|---|
| Bucket | string | 桶名稱 | 是 |
| Key | string | 源對象key | 是 |
返回結果
| 參數 | 類型 | 說明 |
|---|
| CopyPartResult | CopyPartResult | 包含拷貝分片的Entity Tag和最后修改時間等信息 |
取消分片上傳任務
功能說明
您可以使(shi)用abort_multipart_upload終止一個分片上傳(chuan)任務(wu)。
代碼示例
def abort_multipart_upload(self):
print('abort_multipart_upload')
key = '<your-object-key>'
upload_id = '<upload-id>'
resp = self.s3_client.abort_multipart_upload(
Bucket='<your-bucket-name>',
Key=key,
UploadId=upload_id,
)
print(resp)
請求參數
| 參數 | 類型 | 說明 | 是否必要 |
|---|
| Bucket | string | 桶名稱 | 是 |
| Key | string | 對象key | 是 |
| UploadId | string | 需要終止的上傳任務id | 是 |