O recurso de upload multipart do Object Storage Service (OSS) permite dividir um objeto grande em várias partes. Após enviar essas partes, chame a operação CompleteMultipartUpload para combiná-las em um objeto completo.
Observações
O código de exemplo neste tópico usa a região China (Hangzhou) (
cn-hangzhou) e seu endpoint público por padrão. Para acessar o OSS a partir de outros produtos da Alibaba Cloud na mesma região, use um endpoint interno. Para obter mais informações sobre as regiões e os endpoints compatíveis com o OSS, consulte Regions and endpoints.Para fazer um upload multipart, você precisa da permissão
oss:PutObject. Para mais detalhes, consulte Grant a RAM user custom permissions.
Processo de upload multipart
O upload multipart consiste nas três etapas a seguir:
-
Inicialize um evento de upload multipart.
Chame o método Client.InitiateMultipartUpload para obter um ID de upload globalmente exclusivo do OSS.
-
Envie as partes.
Use o método Client.UploadPart para enviar os dados de cada parte.
NotaPara um mesmo ID de upload, o número da parte identifica a parte e sua posição relativa no objeto completo. Se você enviar uma nova parte com um número já existente, a parte anterior no OSS será sobrescrita.
O OSS inclui o hash MD5 dos dados recebidos no cabeçalho ETag da resposta.
O OSS calcula o hash MD5 dos dados enviados e o compara com o hash MD5 calculado pelo software development kit (SDK). Se os dois hashes MD5 forem diferentes, o sistema retornará o código de erro InvalidDigest.
-
Conclua o upload multipart.
Após enviar todas as partes, chame o método Client.CompleteMultipartUpload para mesclar todas as partes em um objeto completo.
Código de exemplo
O exemplo a seguir demonstra como dividir um arquivo local grande em várias partes, enviar essas partes simultaneamente para um bucket e, em seguida, mesclá-las em um objeto completo.
import os
import argparse
import alibabacloud_oss_v2 as oss
# Create a command-line argument parser for the multipart upload sample.
parser = argparse.ArgumentParser(description="multipart upload sample")
# Add the required --region command-line argument, which specifies the region where the bucket is located.
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
# Add the required --bucket command-line argument, which specifies the name of the bucket.
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
# Add the optional --endpoint command-line argument, which specifies the domain name that other services can use to access OSS.
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# Add the required --key command-line argument, which specifies the name of the object.
parser.add_argument('--key', help='The name of the object.', required=True)
# Add the required --file_path command-line argument, which specifies the path of the file to upload.
parser.add_argument('--file_path', help='The path of Upload file.', required=True)
def main():
# Parse the command-line arguments.
args = parser.parse_args()
# Load credentials from environment variables for identity verification.
credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()
# Use the default configurations of the SDK and set the credentials provider.
cfg = oss.config.load_default()
cfg.credentials_provider = credentials_provider
# Set the region in the configuration.
cfg.region = args.region
# If an endpoint is provided, set the endpoint in the configuration.
if args.endpoint is not None:
cfg.endpoint = args.endpoint
# Create an OSS client based on the configuration.
client = oss.Client(cfg)
# Initiate a multipart upload request to obtain the upload ID for subsequent part uploads.
result = client.initiate_multipart_upload(oss.InitiateMultipartUploadRequest(
bucket=args.bucket,
key=args.key,
))
# Define the size of each part as 5 MB.
part_size = 5 * 1024 * 1024
# Obtain the total size of the file to upload.
data_size = os.path.getsize(args.file_path)
# Initialize the part number, starting from 1.
part_number = 1
# Store the result of each part upload.
upload_parts = []
# Open the file in binary read mode.
with open(args.file_path, 'rb') as f:
# Traverse the file and upload it in parts based on part_size.
for start in range(0, data_size, part_size):
n = part_size
if start + n > data_size: # Handle the case where the last part may be smaller than part_size.
n = data_size - start
# Create a SectionReader to read a specific portion of the file.
reader = oss.io_utils.SectionReader(oss.io_utils.ReadAtReader(f), start, n)
# Upload the part.
up_result = client.upload_part(oss.UploadPartRequest(
bucket=args.bucket,
key=args.key,
upload_id=result.upload_id,
part_number=part_number,
body=reader
))
# Print the result of each part upload.
print(f'status code: {up_result.status_code},'
f' request id: {up_result.request_id},'
f' part number: {part_number},'
f' content md5: {up_result.content_md5},'
f' etag: {up_result.etag},'
f' hash crc64: {up_result.hash_crc64},'
)
# Save the part upload result to the list.
upload_parts.append(oss.UploadPart(part_number=part_number, etag=up_result.etag))
# Increment the part number.
part_number += 1
# Sort the uploaded parts by part number.
parts = sorted(upload_parts, key=lambda p: p.part_number)
# Send a request to complete the multipart upload and merge all parts into a complete object.
result = client.complete_multipart_upload(oss.CompleteMultipartUploadRequest(
bucket=args.bucket,
key=args.key,
upload_id=result.upload_id,
complete_multipart_upload=oss.CompleteMultipartUpload(
parts=parts
)
))
# The following code provides another method to list and merge all part data into a complete object on the server.
# This method is suitable when you are not sure whether all parts are successfully uploaded.
# Merge fragmented data into a complete Object through the server-side List method
# result = client.complete_multipart_upload(oss.CompleteMultipartUploadRequest(
# bucket=args.bucket,
# key=args.key,
# upload_id=result.upload_id,
# complete_all='yes'
# ))
# Print the result of the completed multipart upload.
print(f'status code: {result.status_code},'
f' request id: {result.request_id},'
f' bucket: {result.bucket},'
f' key: {result.key},'
f' location: {result.location},'
f' etag: {result.etag},'
f' encoding type: {result.encoding_type},'
f' hash crc64: {result.hash_crc64},'
f' version id: {result.version_id},'
)
if __name__ == "__main__":
main() # The script entry point. The main function is called when the file is run directly.
Cenários comuns
Fazer upload multipart e definir callbacks de upload
Exibir uma barra de progresso para um upload multipart
Referências
Para obter o código de exemplo completo de upload multipart, consulte complete_multipart_upload.py.