Uploading Large Archives Using the Amazon SDK for .NET - Amazon S3 Glacier
Services or capabilities described in Amazon Web Services documentation might vary by Region. To see the differences applicable to the China Regions, see Getting Started with Amazon Web Services in China (PDF).

This page is only for existing customers of the S3 Glacier service using Vaults and the original REST API from 2012.

If you're looking for archival storage solutions we suggest using the S3 Glacier storage classes in Amazon S3, S3 Glacier Instant Retrieval, S3 Glacier Flexible Retrieval, and S3 Glacier Deep Archive. To learn more about these storage options, see S3 Glacier storage classes and Long-term data storage using S3 Glacier storage classes in the Amazon S3 User Guide. These storage classes use the Amazon S3 API, are available in all regions, and can be managed within the Amazon S3 console. They offer features like Storage Cost Analysis, Storage Lens, security features including multiple encryption options, and more.

Uploading Large Archives Using the Amazon SDK for .NET

Both the high-level and low-level APIs provided by the Amazon SDK for .NET provide a method to upload large archives in parts (see Uploading an Archive in Amazon S3 Glacier).

  • The high-level API provides a method that you can use to upload archives of any size. Depending on the file you are uploading, the method either uploads archive in a single operation or uses the multipart upload support in Amazon S3 Glacier (S3 Glacier) to upload the archive in parts.

  • The low-level API maps close to the underlying REST implementation. Accordingly, it provides a method to upload smaller archives in one operation and a group of methods that support multipart upload for larger archives. This section explains uploading large archives in parts using the low-level API.

For more information about the high-level and low-level APIs, see Using the Amazon SDK for .NET with Amazon S3 Glacier.

Uploading Large Archives in Parts Using the High-Level API of the Amazon SDK for .NET

You use the same methods of the high-level API to upload small or large archives. Based on the archive size, the high-level API methods decide whether to upload the archive in a single operation or use the multipart upload API provided by S3 Glacier. For more information, see Uploading an Archive Using the High-Level API of the Amazon SDK for .NET.

Uploading Large Archives in Parts Using the Low-Level API of the Amazon SDK for .NET

For granular control of the upload, you can use the low-level API, where you can configure the request and process the response. The following are the steps to upload large archives in parts using the Amazon SDK for .NET.

  1. Create an instance of the AmazonGlacierClient class (the client).

    You need to specify an Amazon Region where you want to save the archive. All operations you perform using this client apply to that Amazon Region.

  2. Initiate multipart upload by calling the InitiateMultipartUpload method.

    You need to provide the vault name to which you want to upload the archive, the part size you want to use to upload archive parts, and an optional description. You provide this information by creating an instance of the InitiateMultipartUploadRequest class. In response, S3 Glacier returns an upload ID.

  3. Upload parts by calling the UploadMultipartPart method.

    For each part you upload, You need to provide the vault name, the byte range in the final assembled archive that will be uploaded in this part, the checksum of the part data, and the upload ID.

  4. Complete the multipart upload by calling the CompleteMultipartUpload method.

    You need to provide the upload ID, the checksum of the entire archive, the archive size (combined size of all parts you uploaded), and the vault name. S3 Glacier constructs the archive from the uploaded parts and returns an archive ID.

Example: Uploading a Large Archive in Parts Using the Amazon SDK for .NET

The following C# code example uses the Amazon SDK for .NET to upload an archive to a vault (examplevault). For step-by-step instructions on how to run this example, see Running Code Examples. You need to update the code as shown with the name of a file you want to upload.

using System; using System.Collections.Generic; using System.IO; using Amazon.Glacier; using Amazon.Glacier.Model; using Amazon.Runtime; namespace glacier.amazon.com.docsamples { class ArchiveUploadMPU { static string vaultName = "examplevault"; static string archiveToUpload = "*** Provide file name (with full path) to upload ***"; static long partSize = 4194304; // 4 MB. public static void Main(string[] args) { AmazonGlacierClient client; List<string> partChecksumList = new List<string>(); try { using (client = new AmazonGlacierClient(Amazon.RegionEndpoint.USWest2)) { Console.WriteLine("Uploading an archive."); string uploadId = InitiateMultipartUpload(client); partChecksumList = UploadParts(uploadId, client); string archiveId = CompleteMPU(uploadId, client, partChecksumList); Console.WriteLine("Archive ID: {0}", archiveId); } Console.WriteLine("Operations successful. To continue, press Enter"); Console.ReadKey(); } catch (AmazonGlacierException e) { Console.WriteLine(e.Message); } catch (AmazonServiceException e) { Console.WriteLine(e.Message); } catch (Exception e) { Console.WriteLine(e.Message); } Console.WriteLine("To continue, press Enter"); Console.ReadKey(); } static string InitiateMultipartUpload(AmazonGlacierClient client) { InitiateMultipartUploadRequest initiateMPUrequest = new InitiateMultipartUploadRequest() { VaultName = vaultName, PartSize = partSize, ArchiveDescription = "Test doc uploaded using MPU." }; InitiateMultipartUploadResponse initiateMPUresponse = client.InitiateMultipartUpload(initiateMPUrequest); return initiateMPUresponse.UploadId; } static List<string> UploadParts(string uploadID, AmazonGlacierClient client) { List<string> partChecksumList = new List<string>(); long currentPosition = 0; var buffer = new byte[Convert.ToInt32(partSize)]; long fileLength = new FileInfo(archiveToUpload).Length; using (FileStream fileToUpload = new FileStream(archiveToUpload, FileMode.Open, FileAccess.Read)) { while (fileToUpload.Position < fileLength) { Stream uploadPartStream = GlacierUtils.CreatePartStream(fileToUpload, partSize); string checksum = TreeHashGenerator.CalculateTreeHash(uploadPartStream); partChecksumList.Add(checksum); // Upload part. UploadMultipartPartRequest uploadMPUrequest = new UploadMultipartPartRequest() { VaultName = vaultName, Body = uploadPartStream, Checksum = checksum, UploadId = uploadID }; uploadMPUrequest.SetRange(currentPosition, currentPosition + uploadPartStream.Length - 1); client.UploadMultipartPart(uploadMPUrequest); currentPosition = currentPosition + uploadPartStream.Length; } } return partChecksumList; } static string CompleteMPU(string uploadID, AmazonGlacierClient client, List<string> partChecksumList) { long fileLength = new FileInfo(archiveToUpload).Length; CompleteMultipartUploadRequest completeMPUrequest = new CompleteMultipartUploadRequest() { UploadId = uploadID, ArchiveSize = fileLength.ToString(), Checksum = TreeHashGenerator.CalculateTreeHash(partChecksumList), VaultName = vaultName }; CompleteMultipartUploadResponse completeMPUresponse = client.CompleteMultipartUpload(completeMPUrequest); return completeMPUresponse.ArchiveId; } } }