Copiar un objeto con la carga multiparte
La carga multiparte permite copiar objetos como un conjunto de partes. En esta sección se muestran ejemplos sobre cómo copiar objetos superiores a 5 GB con la Application Programming Interface (API, Interfaz de programación de aplicaciones) de carga multiparte. Para obtener información sobre cargas multiparte, consulte Carga y copia de objetos con la carga multiparte.
Puede copiar objetos inferiores a 5 GB en una sola operación sin utilizar la API de carga multiparte. Puede copiar objetos inferiores a 5 GB mediante la AWS Management Console, la AWS CLI, la API de REST o los AWS SDK. Para obtener más información, consulte Copia, traslado y cambio de nombre de objetos.
Para conocer un procedimiento integral sobre la carga de un objeto con carga multiparte con una suma de comprobación adicional, consulte Tutorial: Cargar un objeto mediante una carga multiparte y verificar la integridad de sus datos.
En la siguiente sección, se muestra cómo copiar un objeto con carga multiparte con la API de REST o los AWS SDK.
Las siguientes secciones de la referencia de API de Amazon Simple Storage Service describen la API de REST para la carga multiparte. Para copiar un objeto existente, utilice la API Upload Part (Copy) y agregue el encabezado de solicitud x-amz-copy-source
a su solicitud a fin de especificar el objeto de origen.
Puede utilizar estas API para realizar sus propias solicitudes REST o puede utilizar uno de los SDK que ofrecemos. Para obtener más información sobre el uso de la carga multiparte con la AWS CLI, consulte Uso de la AWS CLI. Para obtener más información sobre SDKs, consulte Compatibilidad de AWS SDK con cargas multiparte.
Para copiar un objeto con la API de bajo nivel, siga estos pasos:
-
Inicie una carga multiparte con el llamado al método AmazonS3Client.initiateMultipartUpload()
.
-
Guarde el ID de carga del objeto de respuesta que devuelve el método AmazonS3Client.initiateMultipartUpload()
. Facilite este ID de carga para cada operación de carga de parte.
-
Copie todas las partes. Para cada parte que necesite copiar, cree una nueva instancia de la clase CopyPartRequest
. Proporcione la información de parte, incluidos los nombres de los bucket de origen y destino, las claves de los objetos de origen y de destino, los ID de carga, las ubicaciones del primer y último byte de la parte y el número de parte.
-
Guarde las respuestas de las llamadas del método AmazonS3Client.copyPart()
. Cada respuesta incluye el valor de ETag
y el número de parte de la parte cargada. Necesitará esta información para completar la carga multiparte:
-
Llame al método AmazonS3Client.completeMultipartUpload()
para completar la operación de copia.
- Java
-
En el siguiente ejemplo se muestra cómo usar la API de Java de bajo nivel de Amazon S3 para realizar una copia multiparte. Para obtener instrucciones sobre cómo crear y probar una muestra funcional, consulte Introducción en la Guía del desarrollador de AWS SDK for Java.
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class LowLevelMultipartCopy {
public static void main(String[] args) throws IOException {
Regions clientRegion = Regions.DEFAULT_REGION;
String sourceBucketName = "*** Source bucket name ***";
String sourceObjectKey = "*** Source object key ***";
String destBucketName = "*** Target bucket name ***";
String destObjectKey = "*** Target object key ***";
try {
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withCredentials(new ProfileCredentialsProvider())
.withRegion(clientRegion)
.build();
// Initiate the multipart upload.
InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(destBucketName,
destObjectKey);
InitiateMultipartUploadResult initResult = s3Client.initiateMultipartUpload(initRequest);
// Get the object size to track the end of the copy operation.
GetObjectMetadataRequest metadataRequest = new GetObjectMetadataRequest(sourceBucketName, sourceObjectKey);
ObjectMetadata metadataResult = s3Client.getObjectMetadata(metadataRequest);
long objectSize = metadataResult.getContentLength();
// Copy the object using 5 MB parts.
long partSize = 5 * 1024 * 1024;
long bytePosition = 0;
int partNum = 1;
List<CopyPartResult> copyResponses = new ArrayList<CopyPartResult>();
while (bytePosition < objectSize) {
// The last part might be smaller than partSize, so check to make sure
// that lastByte isn't beyond the end of the object.
long lastByte = Math.min(bytePosition + partSize - 1, objectSize - 1);
// Copy this part.
CopyPartRequest copyRequest = new CopyPartRequest()
.withSourceBucketName(sourceBucketName)
.withSourceKey(sourceObjectKey)
.withDestinationBucketName(destBucketName)
.withDestinationKey(destObjectKey)
.withUploadId(initResult.getUploadId())
.withFirstByte(bytePosition)
.withLastByte(lastByte)
.withPartNumber(partNum++);
copyResponses.add(s3Client.copyPart(copyRequest));
bytePosition += partSize;
}
// Complete the upload request to concatenate all uploaded parts and make the
// copied object available.
CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest(
destBucketName,
destObjectKey,
initResult.getUploadId(),
getETags(copyResponses));
s3Client.completeMultipartUpload(completeRequest);
System.out.println("Multipart copy complete.");
} catch (AmazonServiceException e) {
// The call was transmitted successfully, but Amazon S3 couldn't process
// it, so it returned an error response.
e.printStackTrace();
} catch (SdkClientException e) {
// Amazon S3 couldn't be contacted for a response, or the client
// couldn't parse the response from Amazon S3.
e.printStackTrace();
}
}
// This is a helper function to construct a list of ETags.
private static List<PartETag> getETags(List<CopyPartResult> responses) {
List<PartETag> etags = new ArrayList<PartETag>();
for (CopyPartResult response : responses) {
etags.add(new PartETag(response.getPartNumber(), response.getETag()));
}
return etags;
}
}
- .NET
-
En el siguiente ejemplo de código C#, se muestra cómo usar AWS SDK for .NET para copiar un objeto de Amazon S3 mayor que 5 GB de una ubicación de origen a otra, como, por ejemplo, de un bucket a otro. Para copiar objetos menores de 5 GB, use el procedimiento de copia de una sola operación descrito en Uso de los AWS SDK. Para obtener más información acerca de las cargas multiparte en Amazon S3, consulte Carga y copia de objetos con la carga multiparte.
En este ejemplo, se muestra cómo copiar un objeto de Amazon S3 con un tamaño superior a 5 GB de un bucket de S3 a otro con la API de carga multiparte de AWS SDK for .NET.
using Amazon;
using Amazon.S3;
using Amazon.S3.Model;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Amazon.DocSamples.S3
{
class CopyObjectUsingMPUapiTest
{
private const string sourceBucket = "*** provide the name of the bucket with source object ***";
private const string targetBucket = "*** provide the name of the bucket to copy the object to ***";
private const string sourceObjectKey = "*** provide the name of object to copy ***";
private const string targetObjectKey = "*** provide the name of the object copy ***";
// Specify your bucket region (an example region is shown).
private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2;
private static IAmazonS3 s3Client;
public static void Main()
{
s3Client = new AmazonS3Client(bucketRegion);
Console.WriteLine("Copying an object");
MPUCopyObjectAsync().Wait();
}
private static async Task MPUCopyObjectAsync()
{
// Create a list to store the upload part responses.
List<UploadPartResponse> uploadResponses = new List<UploadPartResponse>();
List<CopyPartResponse> copyResponses = new List<CopyPartResponse>();
// Setup information required to initiate the multipart upload.
InitiateMultipartUploadRequest initiateRequest =
new InitiateMultipartUploadRequest
{
BucketName = targetBucket,
Key = targetObjectKey
};
// Initiate the upload.
InitiateMultipartUploadResponse initResponse =
await s3Client.InitiateMultipartUploadAsync(initiateRequest);
// Save the upload ID.
String uploadId = initResponse.UploadId;
try
{
// Get the size of the object.
GetObjectMetadataRequest metadataRequest = new GetObjectMetadataRequest
{
BucketName = sourceBucket,
Key = sourceObjectKey
};
GetObjectMetadataResponse metadataResponse =
await s3Client.GetObjectMetadataAsync(metadataRequest);
long objectSize = metadataResponse.ContentLength; // Length in bytes.
// Copy the parts.
long partSize = 5 * (long)Math.Pow(2, 20); // Part size is 5 MB.
long bytePosition = 0;
for (int i = 1; bytePosition < objectSize; i++)
{
CopyPartRequest copyRequest = new CopyPartRequest
{
DestinationBucket = targetBucket,
DestinationKey = targetObjectKey,
SourceBucket = sourceBucket,
SourceKey = sourceObjectKey,
UploadId = uploadId,
FirstByte = bytePosition,
LastByte = bytePosition + partSize - 1 >= objectSize ? objectSize - 1 : bytePosition + partSize - 1,
PartNumber = i
};
copyResponses.Add(await s3Client.CopyPartAsync(copyRequest));
bytePosition += partSize;
}
// Set up to complete the copy.
CompleteMultipartUploadRequest completeRequest =
new CompleteMultipartUploadRequest
{
BucketName = targetBucket,
Key = targetObjectKey,
UploadId = initResponse.UploadId
};
completeRequest.AddPartETags(copyResponses);
// Complete the copy.
CompleteMultipartUploadResponse completeUploadResponse =
await s3Client.CompleteMultipartUploadAsync(completeRequest);
}
catch (AmazonS3Exception e)
{
Console.WriteLine("Error encountered on server. Message:'{0}' when writing an object", e.Message);
}
catch (Exception e)
{
Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
}
}
}
}