Por padrão, ao fazer upload de um objeto com o mesmo nome de um objeto existente, o novo objeto substitui o anterior. Este tópico descreve como configurar o cabeçalho de solicitação x-oss-forbid-overwrite para impedir que objetos existentes sejam substituídos por objetos com nomes idênticos durante operações de cópia, upload simples ou multipart upload.
Observações
Este tópico utiliza o endpoint público da região China (Hangzhou). Para acessar o OSS a partir de outros serviços da Alibaba Cloud na mesma região, utilize um endpoint interno. Para mais informações sobre regiões e endpoints do OSS, consulte Regiões e endpoints.
As credenciais de acesso neste exemplo são obtidas de variáveis de ambiente. Para saber como configurar suas credenciais de acesso, consulte Configurar credenciais de acesso (Python SDK V1).
Este tópico demonstra a criação de uma instância OSSClient com um endpoint do OSS. Para configurações alternativas, como uso de domínio personalizado ou autenticação via Security Token Service (STS), consulte Inicialização.
Evitar substituições em tarefas de upload simples
O código de exemplo abaixo mostra como impedir que objetos existentes sejam substituídos por novos objetos com o mesmo nome durante um upload simples:
# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
# Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
# Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com.
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
# Specify the ID of the region that maps to the endpoint. Example: cn-hangzhou. This parameter is required if you use the signature algorithm V4.
region = "cn-hangzhou"
# Specify the name of your bucket.
bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region)
# Upload the object.
# Specify whether the object that is uploaded by calling the PutObject operation overwrites the existing object that has the same name.
# By default, if x-oss-forbid-overwrite is not specified, the object that is uploaded overwrites the existing object that has the same name.
# If x-oss-forbid-overwrite is set to false, the object that is uploaded overwrites the existing object that has the same name.
# If x-oss-forbid-overwrite is set to true, the object that is uploaded cannot overwrite the existing object that has the same name. If an object that has the same name exists in the bucket, OSS returns an error.
headers = {'x-oss-forbid-overwrite': 'true'}
result = bucket.put_object('yourObjectName', 'content of object', headers=headers)
# Display the returned HTTP status code.
print('http status: {0}'.format(result.status))
# Display the request ID. A request ID uniquely identifies a request. We recommend that you add this parameter to the logs.
print('request_id: {0}'.format(result.request_id))
# Display the ETag value returned by the put_object method.
print('ETag: {0}'.format(result.etag))
# Display the HTTP response headers.
print('date: {0}'.format(result.headers['date']))
Evitar substituições em tarefas de cópia de objetos
-
Copiar um objeto pequeno
O exemplo a seguir ilustra como copiar um objeto pequeno sem substituir um objeto existente com o mesmo nome:
# -*- coding: utf-8 -*- import oss2 from oss2.credentials import EnvironmentVariableCredentialsProvider # Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider()) # Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. # Specify the name of your bucket. bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'yourBucketName') # Specify whether the object that is copied by calling the copy_object operation overwrites the existing object that has the same name. # By default, if x-oss-forbid-overwrite is not specified, an existing object is overwritten by a copied object with the same name. # If x-oss-forbid-overwrite is set to false, an existing object is overwritten by a copied object with the same name. # If x-oss-forbid-overwrite is set to true, an existing object is not overwritten by a copied object with the same name. If the existing object has the same name as the copied object, an error is reported. headers = dict() headers = {'x-oss-forbid-overwrite':'true'} bucket.copy_object('yourSourceBucketName', 'yourSourceObjectName', 'yourDestinationObjectName', headers=headers) -
Copiar um objeto grande
Para evitar que um objeto grande existente seja substituído durante uma cópia multipart, utilize o código abaixo:
# -*- coding: utf-8 -*- import oss2 from oss2.credentials import EnvironmentVariableCredentialsProvider from oss2.models import PartInfo from oss2 import determine_part_size # Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider()) # Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. endpoint = "https://oss-cn-hangzhou.aliyuncs.com" # Specify the ID of the region that maps to the endpoint. Example: cn-hangzhou. This parameter is required if you use the signature algorithm V4. region = "cn-hangzhou" # Specify the name of your bucket. bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region) src_object = 'yourSourceObjectName' dst_object = 'yourDestinationObjectName' total_size = bucket.head_object(src_object).content_length part_size = determine_part_size(total_size, preferred_size=100 * 1024) # Initiate a multipart upload task. # Specify whether to overwrite an object that has the same name when you copy an object. # By default, if x-oss-forbid-overwrite is not specified, the object that is copied overwrites the existing object that has the same name. # If x-oss-forbid-overwrite is set to false, the object that is copied overwrites the existing object that has the same name. # If x-oss-forbid-overwrite is set to true, an existing object is not overwritten by a copied object with the same name. If the existing object has the same name as the copied object, an error is reported. headers = dict() headers = {'x-oss-forbid-overwrite': 'true'} upload_id = bucket.init_multipart_upload(dst_object, headers=headers).upload_id parts = [] # Copy each part. part_number = 1 offset = 0 while offset < total_size: num_to_upload = min(part_size, total_size - offset) byte_range = (offset, offset + num_to_upload - 1) result = bucket.upload_part_copy(bucket.bucket_name, src_object, byte_range,dst_object, upload_id, part_number) parts.append(PartInfo(part_number, result.etag)) offset += num_to_upload part_number += 1 # Complete the multipart copy task. # Specify whether to overwrite an object that has the same name when you copy an object. # By default, if x-oss-forbid-overwrite is not specified, the object that is uploaded overwrites the existing object that has the same name. # If x-oss-forbid-overwrite is set to false, the object that is uploaded overwrites the existing object that has the same name. # If x-oss-forbid-overwrite is set to true, an existing object is not overwritten by a copied object with the same name. If the existing object has the same name as the copied object, an error is reported. headers = dict() headers = {'x-oss-forbid-overwrite':'true'} bucket.complete_multipart_upload(dst_object, upload_id, parts, headers=headers)
Evitar substituições em tarefas de multipart upload
Ao realizar uploads de grandes volumes de dados via multipart upload, siga este exemplo para garantir que objetos existentes com o mesmo nome não sejam substituídos:
# -*- coding: utf-8 -*-
import os
from oss2 import SizedFileAdapter, determine_part_size
from oss2.models import PartInfo
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
# Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
# Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com.
endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
# Specify the ID of the region that maps to the endpoint. Example: cn-hangzhou. This parameter is required if you use the signature algorithm V4.
region = "cn-hangzhou"
# Specify the name of your bucket.
bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region)
key = 'yourObjectName'
filename = 'yourLocalFile'
total_size = os.path.getsize(filename)
# Specify the determine_part_size method to determine the part size.
part_size = determine_part_size(total_size, preferred_size=100 * 1024)
# Initiate a multipart upload task.
# Specify whether to overwrite the existing object that has the same name when you perform multipart upload.
# By default, if x-oss-forbid-overwrite is not specified, the object that is uploaded overwrites the existing object that has the same name.
# If x-oss-forbid-overwrite is set to false, the object that is uploaded overwrites the existing object that has the same name.
# If x-oss-forbid-overwrite is set to true, the object that is uploaded cannot overwrite the existing object that has the same name. If an object that has the same name exists in the bucket, OSS returns an error.
headers = {'x-oss-forbid-overwrite': 'true'}
upload_id = bucket.init_multipart_upload(key, headers=headers).upload_id
parts = []
# Upload the 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)
# The SizedFileAdapter(fileobj, size) method generates a new object and recalculates the position from which the append operation starts.
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
# Complete the multipart upload task.
# Specify whether to overwrite the existing object that has the same name when you perform multipart upload.
# By default, if x-oss-forbid-overwrite is not specified, the object that is uploaded overwrites the existing object that has the same name.
# If x-oss-forbid-overwrite is set to false, the object that is uploaded overwrites the existing object that has the same name.
# If x-oss-forbid-overwrite is set to true, the object that is uploaded cannot overwrite the existing object that has the same name. If an object that has the same name exists in the bucket, OSS returns an error.
headers = {'x-oss-forbid-overwrite': 'true'}
bucket.complete_multipart_upload(key, upload_id, parts, headers=headers)
# Verify the result of the multipart upload task.
with open(filename, 'rb') as fileobj:
assert bucket.get_object(key).read() == fileobj.read()
Referências
Para detalhes sobre a operação de API usada em uploads simples, consulte PutObject.
Sobre a operação de API para cópia de objetos, veja CopyObject.
Quanto às operações de API necessárias para multipart upload, acesse InitiateMultipartUpload e CompleteMultipartUpload.