멀티파트 업로드를 사용한 객체 복사 - Amazon Simple Storage Service

멀티파트 업로드를 사용한 객체 복사

멀티파트 업로드를 통해 객체를 여러 부분의 집합으로 복사할 수 있습니다. 이 섹션의 예제는 멀티파트 업로드 API를 사용하여 5GB보다 큰 객체를 복사하는 방법을 보여 줍니다. 멀티파트 업로드에 대한 내용은 Amazon S3에서 멀티파트 업로드를 사용한 객체 업로드 및 복사 섹션을 참조하세요.

멀티파트 업로드 API를 사용하지 않고 단일 작업으로는 5GB보다 작은 객체를 복사할 수 있습니다. AWS Management Console, AWS CLI, REST API 또는 AWS SDK를 사용하여 5GB보다 작은 객체를 복사할 수 있습니다. 자세한 내용은 객체 복사, 이동, 이름 변경 단원을 참조하십시오.

추가 체크섬이 포함된 멀티파트 업로드를 사용하여 객체를 업로드하는 전체 절차는 튜토리얼: 멀티파트 업로드를 통한 객체 업로드 및 데이터 무결성 확인 섹션을 참조하세요.

다음 섹션에서는 REST API 또는 AWS SDK를 사용하여 멀티파트 업로드로 객체를 복사하는 방법을 보여줍니다.

Amazon Simple Storage Service API 참조의 다음 섹션에서는 멀티파트 업로드를 위한 REST API에 대해 설명합니다. 기존 객체를 복사하려면, 파트 업로드(복사) API를 사용하고 요청에 x-amz-copy-source 요청 헤더를 추가하여 소스 객체를 지정합니다.

이러한 API를 사용하여 REST 요청을 만들거나, 제공된 SDK 중 하나를 사용할 수 있습니다. AWS CLI에서 멀티파트 업로드를 사용하는 방법에 대한 자세한 내용은 AWS CLI 사용 단원을 참조하십시오. SDK에 대한 자세한 내용은 멀티파트 업로드에 대한 AWS SDK 지원을 참조하십시오.

하위 수준 API를 사용하여 객체를 복사하려면 다음을 수행합니다.

  • AmazonS3Client.initiateMultipartUpload() 메서드를 호출하여 멀티파트 업로드를 시작합니다.

  • AmazonS3Client.initiateMultipartUpload() 메서드가 반환하는 응답 객체에서 업로드 ID를 저장합니다. 이후의 각 파트 업로드 작업에서 이 업로드 ID를 제공합니다.

  • 모든 파트를 복사합니다. 복사해야 하는 각 파트에 대해 CopyPartRequest 클래스의 새 인스턴스를 생성합니다. 소스 및 대상 버킷 이름, 소스 및 대상 객체 키, 업로드 ID, 파트의 첫 번째 및 마지막 바이트 위치와 파트 번호 등과 같은 파트 정보를 제공합니다.

  • AmazonS3Client.copyPart() 메서드 호출에 대한 응답을 저장합니다. 각 응답에는 업로드된 파트의 파트 번호화 ETag 값이 포함되어 있습니다. 멀티파트 업로드를 완료하려면 이러한 정보가 필요합니다.

  • AmazonS3Client.completeMultipartUpload() 메서드를 호출하여 복사 작업을 완료합니다.

Java

다음 예제에서는 Amazon S3 하위 수준 Java API를 사용하여 멀티파트 복사를 수행하는 방법을 보여줍니다. 실제 예제를 작성 및 테스트하는 방법에 대한 자세한 내용은 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

다음 C# 예제는 AWS SDK for .NET을 사용하여 5GB보다 큰 Amazon S3 객체를 하나의 소스 위치에서 다른 위치(예: 한 버킷에서 다른 버킷으로)로 복사합니다. 5GB보다 작은 객체를 복사하려면 AWS SDK 사용에 설명된 단일 작업 복사 프로시저를 사용하십시오. Amazon S3 멀티파트 업로드에 대한 자세한 내용은 Amazon S3에서 멀티파트 업로드를 사용한 객체 업로드 및 복사 단원을 참조하십시오.

이 예제에서는 AWS SDK for .NET 멀티파트 업로드 API를 사용하여 S3 버킷 간에 5GB보다 큰 Amazon S3 객체를 복사하는 방법을 보여 줍니다.

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); } } } }