在OSS中,操作的基本資料單元是檔案(Object)。OSS Python SDK提供了豐富的檔案上傳方式:
- 簡單上傳:檔案最大不能超過5GB。
- 追加上傳:檔案最大不能超過5GB。
- 斷點續傳上傳:支援並發、斷點續傳、自訂分區大小。大檔案上傳推薦使用斷點續傳。最大不能超過48.8TB。
- 分區上傳:當檔案較大時,可以使用分區上傳,最大不能超過48.8TB。
說明:各種上傳方式的適用場景請參見開發指南中的上傳檔案。
上傳過程中,您還可以通過上傳進度條功能查看上傳進度。上傳完成後,您還可以進行上傳回調。
簡單上傳
通過bucket.put_object方法上傳檔案。上傳方法支援多種類型的輸入源,輸入源有如下幾種類型:
類型 | 上傳方式 |
---|---|
字元串 | 直接上傳 |
Bytes | 直接上傳 |
Unicode | 自動轉換為UTF-8編碼的Bytes進行上傳 |
本地檔案 | 檔案對象(File Object),必須以二進位方式開啟(如“rb”模式) |
網路流 | 可迭代對象(Iterable),以Chunked Encoding的方式上傳 |
上傳字元串
以下代碼用於上傳字元串:
# -*- coding: utf-8 -*-
import oss2
# 阿里雲主帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM帳號進行API訪問或日常運維,請登入 https://ram.console.aliyun.com 建立RAM帳號。
auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
# Endpoint以杭州為例,其它Region請按實際情況填寫。
bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')
# 傳回值。
result = bucket.put_object('<yourObjectName>', 'content of object')
# HTTP返回碼。
print('http status: {0}'.format(result.status))
# 請求ID。請求ID是請求的唯一標識,強烈建議在程式日誌中添加此參數。
print('request_id: {0}'.format(result.request_id))
# ETag是put_object方法傳回值特有的屬性。
print('ETag: {0}'.format(result.etag))
# HTTP回應標頭部。
print('date: {0}'.format(result.headers['date']))
上傳Bytes
以下代碼用於上傳Bytes:
# -*- coding: utf-8 -*-
import oss2
# 阿里雲主帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM帳號進行API訪問或日常運維,請登入 https://ram.console.aliyun.com 建立RAM帳號。
auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
# Endpoint以杭州為例,其它Region請按實際情況填寫。
bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')
bucket.put_object('<yourObjectName>', b'content of object')
上傳Unicode
以下代碼用於上傳Unicode:
# -*- coding: utf-8 -*-
import oss2
# 阿里雲主帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM帳號進行API訪問或日常運維,請登入 https://ram.console.aliyun.com 建立RAM帳號。
auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
# Endpoint以杭州為例,其它Region請按實際情況填寫。
bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')
bucket.put_object('<yourObjectName>', u'content of object')
上傳本地檔案
以下代碼用於上傳本地檔案:
# -*- coding: utf-8 -*-
import oss2
# 阿里雲主帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM帳號進行API訪問或日常運維,請登入 https://ram.console.aliyun.com 建立RAM帳號。
auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
# Endpoint以杭州為例,其它Region請按實際情況填寫。
bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')
# 必須以二進位的方式開啟檔案,因為需要知道檔案包含的位元組數。
with open('<yourLocalFile>', 'rb') as fileobj:
# Seek方法用於指定從第1000個位元組位置開始讀寫。上傳時會從您指定的第1000個位元組位置開始上傳,直到檔案結束。
fileobj.seek(1000, os.SEEK_SET)
# Tell方法用於返回當前位置。
current = fileobj.tell()
bucket.put_object('<yourObjectName>', fileobj)
Python SDK還提供了一個更加便捷的方法用於上傳本地檔案:
bucket.put_object_from_file('<yourObjectName>', '<yourLocalFile>')
上傳網路流
以下代碼用於上傳網路流:
# -*- coding: utf-8 -*-
import oss2
import requests
# 阿里雲主帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM帳號進行API訪問或日常運維,請登入 https://ram.console.aliyun.com 建立RAM帳號。
auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
# Endpoint以杭州為例,其它Region請按實際情況填寫。
bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')
# requests.get返回的是一個可迭代對象(Iterable),此時Python SDK會通過Chunked Encoding方式上傳。
input = requests.get('http://www.aliyun.com')
bucket.put_object('<yourObjectName>', input)
追加上傳
以下代碼用於追加上傳檔案:
# -*- coding: utf-8 -*-
import oss2
# 阿里雲主帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM帳號進行API訪問或日常運維,請登入 https://ram.console.aliyun.com 建立RAM帳號。
auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
# Endpoint以杭州為例,其它Region請按實際情況填寫。
bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')
# 設定首次上傳的追加位置(Position參數)為0。
result = bucket.append_object('<yourObjectName>', 0, 'content of first append')
# 如果不是首次上傳,可以通過bucket.head_object方法或上次追加傳回值的next_position屬性,得到追加位置。
bucket.append_object('<yourObjectName>', result.next_position, 'content of second append')
如果檔案已經存在,如下兩種情況將會拋出異常:
- 不是可追加檔案,則拋出ObjectNotAppendable異常。
- 是可追加檔案,但設定的追加位置和檔案當前長度不等,則拋出PositionNotEqualToLength異常。
斷點續傳上傳
斷點續傳上傳將要上傳的檔案分成若干個分區(Part)分別上傳,所有分區都上傳完成後,將所有分區合并成完整的檔案,完成整個檔案的上傳。
您可以通過oss2.resumable_upload方法斷點續傳上傳指定檔案,該方法包含以下參數:
參數 | 描述 | 是否必需 | 預設值 |
---|---|---|---|
bucket | 儲存空間名稱 | 是 | 無 |
key | 檔案名稱 | 是 | 無 |
filename | 待上傳的本地檔案名稱 | 是 | 無 |
store | 指定保存斷點資訊的目錄 | 否 | HOME目錄下建立的.py-oss-upload目錄 |
headers | HTTP頭部 | 否 | 無 |
multipart_threshold | 檔案長度大於該值時,則用分區上傳 | 否 | 10MB |
part_size | 分區大小 | 否 | 自動計算 |
progress_callback | 上傳進度回呼函數 | 否 | 無 |
num_threads | 並發上傳的線程數 | 否 | 1 |
以下代碼用於斷點續傳上傳:
# -*- coding: utf-8 -*-
import oss2
# 阿里雲主帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM帳號進行API訪問或日常運維,請登入 https://ram.console.aliyun.com 建立RAM帳號。
auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
# Endpoint以杭州為例,其它Region請按實際情況填寫。
bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')
# 當檔案長度大於或等於選擇性參數multipart_threshold(預設值為10MB)時,會使用分區上傳。如未使用參數store指定目錄,則會在HOME目錄下建立.py-oss-upload目錄來保存斷點資訊。
oss2.resumable_upload(bucket, '<yourObjectName>', '<yourLocalFile>')
Python SDK 2.1.0以上版本支援設定選擇性參數進行斷點續傳上傳,代碼如下:
# 如使用store指定了目錄,則保存斷點資訊在指定目錄中。如使用num_threads設定上傳並發數,請將oss2.defaults.connection_pool_size設成大於或等於線程數。預設線程數為1。
oss2.resumable_upload(bucket, '<yourObjectName>', '<yourLocalFile>',
store=oss2.ResumableStore(root='/tmp'),
multipart_threshold=100*1024,
part_size=100*1024,
num_threads=4)
斷點續傳詳情請參見開發指南中的斷點續傳。
分區上傳
分區上傳(Multipart Upload)分為以下三個步驟:
- 初始化(bucket.init_multipart_upload):獲得Upload ID。
- 上傳分區(bucket.upload_part):上傳分區資料。這一步可以並發進行。
- 完成上傳(bucket.complete_multipart_upload):所有分區上傳完成後,合并分區,生成OSS檔案。
以下代碼用於分區上傳檔案:
# -*- coding: utf-8 -*-
import os
from oss2 import SizedFileAdapter, determine_part_size
from oss2.models import PartInfo
import oss2
# 阿里雲主帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM帳號進行API訪問或日常運維,請登入 https://ram.console.aliyun.com 建立RAM帳號。
auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
# Endpoint以杭州為例,其它Region請按實際情況填寫。
bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')
key = '<yourObjectName>'
filename = '<yourLocalFile>'
total_size = os.path.getsize(filename)
# determine_part_size方法用來確定分區大小。
part_size = determine_part_size(total_size, preferred_size=100 * 1024)
# 初始化分區。
upload_id = bucket.init_multipart_upload(key).upload_id
parts = []
# 逐個上傳分區。
with open(filename, '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))
parts.append(PartInfo(part_number, result.etag))
offset += num_to_upload
part_number += 1
# 完成分區上傳。
bucket.complete_multipart_upload(key, upload_id, parts)
# 驗證分區上傳。
with open(filename, 'rb') as fileobj:
assert bucket.get_object(key).read() == fileobj.read()
上傳進度條
進度條用於指示上傳或下載的進度。下面的代碼以bucket.put_object方法為例,介紹如何使用進度條。
# -*- coding: utf-8 -*-
from __future__ import print_function
import os, sys
import oss2
# 阿里雲主帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM帳號進行API訪問或日常運維,請登入 https://ram.console.aliyun.com 建立RAM帳號。
auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
# Endpoint以杭州為例,其它Region請按實際情況填寫。
bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')
# 當無法確定待上傳的資料長度時,total_bytes的值為None。
def percentage(consumed_bytes, total_bytes):
if total_bytes:
rate = int(100 * (float(consumed_bytes) / float(total_bytes)))
print('\r{0}% '.format(rate), end='')
sys.stdout.flush()
# progress_callback為選擇性參數,用於實現進度條功能。
bucket.put_object('<yourObjectName>', 'a'*1024*1024, progress_callback=percentage)
進度條的完整範例程式碼請參見GitHub。
上傳回調
以下代碼用於上傳回調:
# -*- coding: utf-8 -*-
import json
import base64
import os
import oss2
# 阿里雲主帳號AccessKey擁有所有API的存取權限,風險很高。強烈建議您建立並使用RAM帳號進行API訪問或日常運維,請登入 https://ram.console.aliyun.com 建立RAM帳號。
auth = oss2.Auth('<yourAccessKeyId>', '<yourAccessKeySecret>')
# Endpoint以杭州為例,其它Region請按實際情況填寫。
bucket = oss2.Bucket(auth, 'http://oss-cn-hangzhou.aliyuncs.com', '<yourBucketName>')
# 準備回調參數。
callback_dict = {}
# 設定回調請求的伺服器位址,如http://oss-demo.aliyuncs.com:23450或http://127.0.0.1:9090。
callback_dict['callbackUrl'] = 'http://oss-demo.aliyuncs.com:23450'
# 設定回調請求消息頭中Host的值, 如oss-cn-hangzhou.aliyuncs.com。
callback_dict['callbackHost'] = 'oss-cn-hangzhou.aliyuncs.com'
# 設定發起回調時請求body的值。
callback_dict['callbackBody'] = 'filename=${object}&size=${size}&mimeType=${mimeType}'
# 設定發起回調請求的Content-Type。
callback_dict['callbackBodyType'] = 'application/x-www-form-urlencoded'
# 回調參數是Json格式,並且需要Base64編碼。
callback_param = json.dumps(callback_dict).strip()
base64_callback_body = base64.b64encode(callback_param)
# 回調參數編碼後放在Header中發送給OSS。
headers = {'x-oss-callback': base64_callback_body}
# 上傳並回調。
result = bucket.put_object('<yourObjectName>', 'a'*1024*1024, headers)
put_object、put_object_from_file、complete_multipart_upload支援上傳回調功能。上傳回調的詳細說明請參見API參考中的上傳回調。上傳回調的完整範例程式碼請參見GitHub。