Téléchargement d'une archive dans Amazon S3 Glacier à l'aide d'AWS SDK for .NET - Amazon S3 Glacier

Cette page est réservée aux clients existants du service S3 Glacier utilisant Vaults et l'original REST API de 2012.

Si vous recherchez des solutions de stockage d'archives, nous vous conseillons d'utiliser les classes de stockage S3 Glacier dans Amazon S3, S3 Glacier Instant Retrieval, S3 Glacier Flexible Retrieval et S3 Glacier Deep Archive. Pour en savoir plus sur ces options de stockage, consultez les sections Classes de stockage S3 Glacier et Stockage de données à long terme à l'aide des classes de stockage S3 Glacier dans le guide de l'utilisateur Amazon S3. Ces classes de stockage utilisent Amazon S3API, sont disponibles dans toutes les régions et peuvent être gérées au sein de la console Amazon S3. Ils offrent des fonctionnalités telles que l'analyse des coûts de stockage, Storage Lens, des fonctionnalités de chiffrement optionnelles avancées, etc.

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Téléchargement d'une archive dans Amazon S3 Glacier à l'aide d'AWS SDK for .NET

Les API de haut et bas niveau fournies par le kit SDK Amazon pour .NET proposent une méthode de téléchargement d'archive.

Téléchargement d'une archive à l'aide de l'API de haut niveau du kit AWS SDK for .NET

La classe ArchiveTransferManager de l'API de haut niveau fournit la méthode Download que vous pouvez utiliser pour télécharger une archive.

Important

La classe ArchiveTransferManager crée une rubrique Amazon Simple Notification Service (Amazon SNS) et une file d'attente Amazon Simple Queue Service (Amazon SQS) qui est abonnée à cette rubrique. Elle lance ensuite la tâche d'extraction d'archive et interroge la file d'attente pour que l'archive soit disponible. Une fois que l'archive est disponible, le téléchargement commence. Pour plus d'informations sur les délais d'extraction, consultez Options de récupération des archives

Exemple : Téléchargement d'une archive à l'aide de l'API de haut niveau du kit AWS SDK for .NET

L'exemple de code C# suivant télécharge une archive à partir d'un coffre (examplevault) de la région USA Ouest (Oregon).

Pour obtenir les instructions étape par étape permettant d'exécuter cet exemple, consultez la section Exemples de code en cours d'exécution. Vous devez mettre à jour le code avec un ID d'archive existant et le chemin d'accès au fichier local où vous souhaitez enregistrer l'archive téléchargée, comme illustré ci-après.

using System; using Amazon.Glacier; using Amazon.Glacier.Transfer; using Amazon.Runtime; namespace glacier.amazon.com.docsamples { class ArchiveDownloadHighLevel { static string vaultName = "examplevault"; static string archiveId = "*** Provide archive ID ***"; static string downloadFilePath = "*** Provide the file name and path to where to store the download ***"; public static void Main(string[] args) { try { var manager = new ArchiveTransferManager(Amazon.RegionEndpoint.USWest2); var options = new DownloadOptions(); options.StreamTransferProgress += ArchiveDownloadHighLevel.progress; // Download an archive. Console.WriteLine("Intiating the archive retrieval job and then polling SQS queue for the archive to be available."); Console.WriteLine("Once the archive is available, downloading will begin."); manager.Download(vaultName, archiveId, downloadFilePath, options); Console.WriteLine("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 int currentPercentage = -1; static void progress(object sender, StreamTransferProgressArgs args) { if (args.PercentDone != currentPercentage) { currentPercentage = args.PercentDone; Console.WriteLine("Downloaded {0}%", args.PercentDone); } } } }

Téléchargement d'une archive à l'aide de l'API de bas niveau du kit AWS SDK for .NET

La procédure ci-dessous décrit les étapes à suivre pour télécharger une archive Amazon S3 Glacier (S3 Glacier) à l'aide de l'API de bas niveau d'AWS SDK for .NET.

  1. Créez une instance de la classe AmazonGlacierClient (le client).

    Vous devez spécifier la région AWS à partir de laquelle vous souhaitez télécharger l'archive. Toutes les opérations que vous effectuez à l'aide de ce client s'appliquent à cette région AWS.

  2. Lancez une tâche archive-retrieval en exécutant la méthode InitiateJob.

    Vous fournissez les informations de la tâche, telles que l'ID de l'archive que vous souhaitez télécharger et la rubrique Amazon SNS facultative dans laquelle vous souhaitez que S3 Glacier publie un message d'achèvement de la tâche, en créant une instance de la classe InitiateJobRequest. S3 Glacier répond en renvoyant un ID de tâche. La réponse est disponible dans une instance de la classe InitiateJobResponse.

    AmazonGlacierClient client; client = new AmazonGlacierClient(Amazon.RegionEndpoint.USWest2); InitiateJobRequest initJobRequest = new InitiateJobRequest() { VaultName = vaultName, JobParameters = new JobParameters() { Type = "archive-retrieval", ArchiveId = "*** Provide archive id ***", SNSTopic = "*** Provide Amazon SNS topic ARN ***", } }; InitiateJobResponse initJobResponse = client.InitiateJob(initJobRequest); string jobId = initJobResponse.JobId;

    Vous pouvez éventuellement spécifier une plage d'octets pour demander à S3 Glacier de ne préparer qu'une partie de l'archive, comme dans la demande suivante. La demande indique à S3 Glacier de préparer uniquement la partie de l'archive entre 1 Mo et 2 Mo.

    AmazonGlacierClient client; client = new AmazonGlacierClient(Amazon.RegionEndpoint.USWest2); InitiateJobRequest initJobRequest = new InitiateJobRequest() { VaultName = vaultName, JobParameters = new JobParameters() { Type = "archive-retrieval", ArchiveId = "*** Provide archive id ***", SNSTopic = "*** Provide Amazon SNS topic ARN ***", } }; // Specify byte range. int ONE_MEG = 1048576; initJobRequest.JobParameters.RetrievalByteRange = string.Format("{0}-{1}", ONE_MEG, 2 * ONE_MEG -1); InitiateJobResponse initJobResponse = client.InitiateJob(initJobRequest); string jobId = initJobResponse.JobId;
  3. Attendez que la tâche se termine.

    Vous devez attendre que la sortie de la tâche soit prête pour pouvoir effectuer le téléchargement. Si vous avez défini pour le coffre une configuration de notifications identifiant une rubrique Amazon Simple Notification Service (Amazon SNS), ou si vous avez spécifié une rubrique Amazon SNS lors du lancement d'une tâche, S3 Glacier envoie un message à cette rubrique une fois qu'il a terminé la tâche. L'exemple de code fourni dans la section suivante utilise Amazon SNS pour permettre à S3 Glacier de publier un message.

    Vous pouvez également interroger S3 Glacier en appelant la méthode DescribeJob pour déterminer le statut d'achèvement de la tâche. Toutefois, l'approche recommandée consiste à utiliser une rubrique Amazon SNS pour la notification.

  4. Téléchargez la sortie de la tâche (données archivées) en exécutant la méthode GetJobOutput.

    Vous indiquez les informations sur la demande, telles que l'ID de la tâche et le nom du coffre, en créant une instance de la classe GetJobOutputRequest. La sortie renvoyée par S3 Glacier est disponible dans l'objet GetJobOutputResponse.

    GetJobOutputRequest getJobOutputRequest = new GetJobOutputRequest() { JobId = jobId, VaultName = vaultName }; GetJobOutputResponse getJobOutputResponse = client.GetJobOutput(getJobOutputRequest); using (Stream webStream = getJobOutputResponse.Body) { using (Stream fileToSave = File.OpenWrite(fileName)) { CopyStream(webStream, fileToSave); } }

    L'extrait de code précédent télécharge la totalité de la sortie de la tâche. Vous pouvez éventuellement extraire une partie de la sortie ou télécharger la totalité de la sortie en plusieurs parties en spécifiant la plage d'octets dans votre demande GetJobOutputRequest.

    GetJobOutputRequest getJobOutputRequest = new GetJobOutputRequest() { JobId = jobId, VaultName = vaultName }; getJobOutputRequest.SetRange(0, 1048575); // Download only the first 1 MB chunk of the output.

    En réponse à votre appel GetJobOutput, S3 Glacier renvoie le total de contrôle de la partie des données que vous avez téléchargées, si certaines conditions sont remplies. Pour de plus amples informations, veuillez consulter Réception des totaux de contrôle lors du téléchargement de données.

    Pour vérifier que le téléchargement ne comporte pas d'erreurs, vous pouvez calculer le total de contrôle côté client et le comparer à celui envoyé dans la réponse de S3 Glacier.

    Dans le cas d'une tâche d'extraction d'archive pour laquelle la plage facultative a été spécifiée, la description de la tâche que vous obtenez inclut le total de contrôle de la plage sur laquelle porte l'extraction (SHA256TreeHash). Vous pouvez utiliser cette valeur pour vérifier de façon plus approfondie la précision de la totalité de la plage d'octets qui fera l'objet d'un téléchargement ultérieur. Par exemple, si vous lancez une tâche pour extraire une plage d'une archive alignée sur le hachage d'arborescence, que vous téléchargez la sortie en plusieurs parties et que chacune de vos demandes GetJobOutput renvoie un total de contrôle, vous pouvez ensuite calculer le total de contrôle de chaque partie téléchargée côté client, puis calculer le hachage d'arborescence. Vous pouvez le comparer au total de contrôle renvoyé par S3 Glacier en réponse à votre demande de description de tâche pour vérifier que la totalité de la plage d'octets que vous avez téléchargée est identique à celle stockée dans S3 Glacier.

    Pour obtenir un exemple pratique, consultez Exemple 2 : Extraction d'une archive à l'aide de l'API de bas niveau d'AWS SDK for .NET – Téléchargement d'une sortie en plusieurs parties.

Exemple 1 : Extraction d'une archive à l'aide de l'API de bas niveau du kit AWS SDK for .NET

L'exemple de code C# suivant télécharge une archive à partir du coffre spécifié. Une fois la tâche terminée, l'exemple télécharge la totalité de la sortie dans un seul appel GetJobOutput. Pour obtenir un exemple de téléchargement d'une sortie en plusieurs parties, consultez la section Exemple 2 : Extraction d'une archive à l'aide de l'API de bas niveau d'AWS SDK for .NET – Téléchargement d'une sortie en plusieurs parties.

L'exemple exécute les tâches suivantes :

  • Configuration d'une rubrique Amazon Simple Notification Service (Amazon SNS).

    S3 Glacier envoie une notification à cette rubrique une fois qu'il a terminé la tâche.

  • Configuration d'une file d'attente Amazon Simple Queue Service (Amazon SQS).

    L'exemple attache une politique à la file d'attente pour permettre à la rubrique Amazon SNS de publier des messages.

  • Lancement d'une tâche de téléchargement de l'archive spécifiée.

    Dans la demande de tâche, l'exemple spécifie la rubrique Amazon SNS pour permettre à S3 Glacier d'envoyer un message une fois qu'il a terminé la tâche.

  • Recherche périodique d'un message dans la file d'attente Amazon SQS.

    Si un message est présent, l'exemple analyse le JSON et vérifie si la tâche s'est correctement déroulée. Si tel est le cas, il télécharge l'archive. L'exemple de code utilise la bibliothèque JSON.NET (consultez le document JSON.NET) pour analyser le JSON.

  • Nettoyage par la suppression de la rubrique Amazon SNS et de la file d'attente Amazon SQS qu'il a créées.

using System; using System.Collections.Generic; using System.IO; using System.Threading; using Amazon.Glacier; using Amazon.Glacier.Model; using Amazon.Runtime; using Amazon.SimpleNotificationService; using Amazon.SimpleNotificationService.Model; using Amazon.SQS; using Amazon.SQS.Model; using Newtonsoft.Json; namespace glacier.amazon.com.docsamples { class ArchiveDownloadLowLevelUsingSNSSQS { static string topicArn; static string queueUrl; static string queueArn; static string vaultName = "*** Provide vault name ***"; static string archiveID = "*** Provide archive ID ***"; static string fileName = "*** Provide the file name and path to where to store downloaded archive ***"; static AmazonSimpleNotificationServiceClient snsClient; static AmazonSQSClient sqsClient; const string SQS_POLICY = "{" + " \"Version\" : \"2012-10-17\"," + " \"Statement\" : [" + " {" + " \"Sid\" : \"sns-rule\"," + " \"Effect\" : \"Allow\"," + " \"Principal\" : {\"Service\" : \"sns.amazonaws.com\" }," + " \"Action\" : \"sqs:SendMessage\"," + " \"Resource\" : \"{QueueArn}\"," + " \"Condition\" : {" + " \"ArnLike\" : {" + " \"aws:SourceArn\" : \"{TopicArn}\"" + " }" + " }" + " }" + " ]" + "}"; public static void Main(string[] args) { AmazonGlacierClient client; try { using (client = new AmazonGlacierClient(Amazon.RegionEndpoint.USWest2)) { Console.WriteLine("Setup SNS topic and SQS queue."); SetupTopicAndQueue(); Console.WriteLine("To continue, press Enter"); Console.ReadKey(); Console.WriteLine("Retrieving..."); RetrieveArchive(client); } 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); } finally { // Delete SNS topic and SQS queue. snsClient.DeleteTopic(new DeleteTopicRequest() { TopicArn = topicArn }); sqsClient.DeleteQueue(new DeleteQueueRequest() { QueueUrl = queueUrl }); } } static void SetupTopicAndQueue() { snsClient = new AmazonSimpleNotificationServiceClient(Amazon.RegionEndpoint.USWest2); sqsClient = new AmazonSQSClient(Amazon.RegionEndpoint.USWest2); long ticks = DateTime.Now.Ticks; topicArn = snsClient.CreateTopic(new CreateTopicRequest { Name = "GlacierDownload-" + ticks }).TopicArn; Console.Write("topicArn: "); Console.WriteLine(topicArn); CreateQueueRequest createQueueRequest = new CreateQueueRequest(); createQueueRequest.QueueName = "GlacierDownload-" + ticks; CreateQueueResponse createQueueResponse = sqsClient.CreateQueue(createQueueRequest); queueUrl = createQueueResponse.QueueUrl; Console.Write("QueueURL: "); Console.WriteLine(queueUrl); GetQueueAttributesRequest getQueueAttributesRequest = new GetQueueAttributesRequest(); getQueueAttributesRequest.AttributeNames = new List<string> { "QueueArn" }; getQueueAttributesRequest.QueueUrl = queueUrl; GetQueueAttributesResponse response = sqsClient.GetQueueAttributes(getQueueAttributesRequest); queueArn = response.QueueARN; Console.Write("QueueArn: "); Console.WriteLine(queueArn); // Setup the Amazon SNS topic to publish to the SQS queue. snsClient.Subscribe(new SubscribeRequest() { Protocol = "sqs", Endpoint = queueArn, TopicArn = topicArn }); // Add policy to the queue so SNS can send messages to the queue. var policy = SQS_POLICY.Replace("{TopicArn}", topicArn).Replace("{QueueArn}", queueArn); sqsClient.SetQueueAttributes(new SetQueueAttributesRequest() { QueueUrl = queueUrl, Attributes = new Dictionary<string, string> { { QueueAttributeName.Policy, policy } } }); } static void RetrieveArchive(AmazonGlacierClient client) { // Initiate job. InitiateJobRequest initJobRequest = new InitiateJobRequest() { VaultName = vaultName, JobParameters = new JobParameters() { Type = "archive-retrieval", ArchiveId = archiveID, Description = "This job is to download archive.", SNSTopic = topicArn, } }; InitiateJobResponse initJobResponse = client.InitiateJob(initJobRequest); string jobId = initJobResponse.JobId; // Check queue for a message and if job completed successfully, download archive. ProcessQueue(jobId, client); } private static void ProcessQueue(string jobId, AmazonGlacierClient client) { ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest() { QueueUrl = queueUrl, MaxNumberOfMessages = 1 }; bool jobDone = false; while (!jobDone) { Console.WriteLine("Poll SQS queue"); ReceiveMessageResponse receiveMessageResponse = sqsClient.ReceiveMessage(receiveMessageRequest); if (receiveMessageResponse.Messages.Count == 0) { Thread.Sleep(10000 * 60); continue; } Console.WriteLine("Got message"); Message message = receiveMessageResponse.Messages[0]; Dictionary<string, string> outerLayer = JsonConvert.DeserializeObject<Dictionary<string, string>>(message.Body); Dictionary<string, object> fields = JsonConvert.DeserializeObject<Dictionary<string, object>>(outerLayer["Message"]); string statusCode = fields["StatusCode"] as string; if (string.Equals(statusCode, GlacierUtils.JOB_STATUS_SUCCEEDED, StringComparison.InvariantCultureIgnoreCase)) { Console.WriteLine("Downloading job output"); DownloadOutput(jobId, client); // Save job output to the specified file location. } else if (string.Equals(statusCode, GlacierUtils.JOB_STATUS_FAILED, StringComparison.InvariantCultureIgnoreCase)) Console.WriteLine("Job failed... cannot download the archive."); jobDone = true; sqsClient.DeleteMessage(new DeleteMessageRequest() { QueueUrl = queueUrl, ReceiptHandle = message.ReceiptHandle }); } } private static void DownloadOutput(string jobId, AmazonGlacierClient client) { GetJobOutputRequest getJobOutputRequest = new GetJobOutputRequest() { JobId = jobId, VaultName = vaultName }; GetJobOutputResponse getJobOutputResponse = client.GetJobOutput(getJobOutputRequest); using (Stream webStream = getJobOutputResponse.Body) { using (Stream fileToSave = File.OpenWrite(fileName)) { CopyStream(webStream, fileToSave); } } } public static void CopyStream(Stream input, Stream output) { byte[] buffer = new byte[65536]; int length; while ((length = input.Read(buffer, 0, buffer.Length)) > 0) { output.Write(buffer, 0, length); } } } }

Exemple 2 : Extraction d'une archive à l'aide de l'API de bas niveau d'AWS SDK for .NET – Téléchargement d'une sortie en plusieurs parties

L'exemple de code C# suivant extrait une archive de S3 Glacier. L'exemple de code télécharge la sortie de la tâche en plusieurs parties en spécifiant la plage d'octets dans un objet GetJobOutputRequest.

using System; using System.Collections.Generic; using System.IO; using System.Threading; using Amazon.Glacier; using Amazon.Glacier.Model; using Amazon.Glacier.Transfer; using Amazon.Runtime; using Amazon.SimpleNotificationService; using Amazon.SimpleNotificationService.Model; using Amazon.SQS; using Amazon.SQS.Model; using Newtonsoft.Json; using System.Collections.Specialized; namespace glacier.amazon.com.docsamples { class ArchiveDownloadLowLevelUsingSQLSNSOutputUsingRange { static string topicArn; static string queueUrl; static string queueArn; static string vaultName = "*** Provide vault name ***"; static string archiveId = "*** Provide archive ID ***"; static string fileName = "*** Provide the file name and path to where to store downloaded archive ***"; static AmazonSimpleNotificationServiceClient snsClient; static AmazonSQSClient sqsClient; const string SQS_POLICY = "{" + " \"Version\" : \"2012-10-17\"," + " \"Statement\" : [" + " {" + " \"Sid\" : \"sns-rule\"," + " \"Effect\" : \"Allow\"," + " \"Principal\" : {\"AWS\" : \"arn:aws:iam::123456789012:root\" }," + " \"Action\" : \"sqs:SendMessage\"," + " \"Resource\" : \"{QuernArn}\"," + " \"Condition\" : {" + " \"ArnLike\" : {" + " \"aws:SourceArn\" : \"{TopicArn}\"" + " }" + " }" + " }" + " ]" + "}"; public static void Main(string[] args) { AmazonGlacierClient client; try { using (client = new AmazonGlacierClient(Amazon.RegionEndpoint.USWest2)) { Console.WriteLine("Setup SNS topic and SQS queue."); SetupTopicAndQueue(); Console.WriteLine("To continue, press Enter"); Console.ReadKey(); Console.WriteLine("Download archive"); DownloadAnArchive(archiveId, client); } 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); } finally { // Delete SNS topic and SQS queue. snsClient.DeleteTopic(new DeleteTopicRequest() { TopicArn = topicArn }); sqsClient.DeleteQueue(new DeleteQueueRequest() { QueueUrl = queueUrl }); } } static void SetupTopicAndQueue() { long ticks = DateTime.Now.Ticks; // Setup SNS topic. snsClient = new AmazonSimpleNotificationServiceClient(Amazon.RegionEndpoint.USWest2); sqsClient = new AmazonSQSClient(Amazon.RegionEndpoint.USWest2); topicArn = snsClient.CreateTopic(new CreateTopicRequest { Name = "GlacierDownload-" + ticks }).TopicArn; Console.Write("topicArn: "); Console.WriteLine(topicArn); CreateQueueRequest createQueueRequest = new CreateQueueRequest(); createQueueRequest.QueueName = "GlacierDownload-" + ticks; CreateQueueResponse createQueueResponse = sqsClient.CreateQueue(createQueueRequest); queueUrl = createQueueResponse.QueueUrl; Console.Write("QueueURL: "); Console.WriteLine(queueUrl); GetQueueAttributesRequest getQueueAttributesRequest = new GetQueueAttributesRequest(); getQueueAttributesRequest.AttributeNames = new List<string> { "QueueArn" }; getQueueAttributesRequest.QueueUrl = queueUrl; GetQueueAttributesResponse response = sqsClient.GetQueueAttributes(getQueueAttributesRequest); queueArn = response.QueueARN; Console.Write("QueueArn: "); Console.WriteLine(queueArn); // Setup the Amazon SNS topic to publish to the SQS queue. snsClient.Subscribe(new SubscribeRequest() { Protocol = "sqs", Endpoint = queueArn, TopicArn = topicArn }); // Add the policy to the queue so SNS can send messages to the queue. var policy = SQS_POLICY.Replace("{TopicArn}", topicArn).Replace("{QuernArn}", queueArn); sqsClient.SetQueueAttributes(new SetQueueAttributesRequest() { QueueUrl = queueUrl, Attributes = new Dictionary<string, string> { { QueueAttributeName.Policy, policy } } }); } static void DownloadAnArchive(string archiveId, AmazonGlacierClient client) { // Initiate job. InitiateJobRequest initJobRequest = new InitiateJobRequest() { VaultName = vaultName, JobParameters = new JobParameters() { Type = "archive-retrieval", ArchiveId = archiveId, Description = "This job is to download the archive.", SNSTopic = topicArn, } }; InitiateJobResponse initJobResponse = client.InitiateJob(initJobRequest); string jobId = initJobResponse.JobId; // Check queue for a message and if job completed successfully, download archive. ProcessQueue(jobId, client); } private static void ProcessQueue(string jobId, AmazonGlacierClient client) { var receiveMessageRequest = new ReceiveMessageRequest() { QueueUrl = queueUrl, MaxNumberOfMessages = 1 }; bool jobDone = false; while (!jobDone) { Console.WriteLine("Poll SQS queue"); ReceiveMessageResponse receiveMessageResponse = sqsClient.ReceiveMessage(receiveMessageRequest); if (receiveMessageResponse.Messages.Count == 0) { Thread.Sleep(10000 * 60); continue; } Console.WriteLine("Got message"); Message message = receiveMessageResponse.Messages[0]; Dictionary<string, string> outerLayer = JsonConvert.DeserializeObject<Dictionary<string, string>>(message.Body); Dictionary<string, object> fields = JsonConvert.DeserializeObject<Dictionary<string, object>>(outerLayer["Message"]); string statusCode = fields["StatusCode"] as string; if (string.Equals(statusCode, GlacierUtils.JOB_STATUS_SUCCEEDED, StringComparison.InvariantCultureIgnoreCase)) { long archiveSize = Convert.ToInt64(fields["ArchiveSizeInBytes"]); Console.WriteLine("Downloading job output"); DownloadOutput(jobId, archiveSize, client); // This where we save job output to the specified file location. } else if (string.Equals(statusCode, GlacierUtils.JOB_STATUS_FAILED, StringComparison.InvariantCultureIgnoreCase)) Console.WriteLine("Job failed... cannot download the archive."); jobDone = true; sqsClient.DeleteMessage(new DeleteMessageRequest() { QueueUrl = queueUrl, ReceiptHandle = message.ReceiptHandle }); } } private static void DownloadOutput(string jobId, long archiveSize, AmazonGlacierClient client) { long partSize = 4 * (long)Math.Pow(2, 20); // 4 MB. using (Stream fileToSave = new FileStream(fileName, FileMode.Create, FileAccess.Write)) { long currentPosition = 0; do { GetJobOutputRequest getJobOutputRequest = new GetJobOutputRequest() { JobId = jobId, VaultName = vaultName }; long endPosition = currentPosition + partSize - 1; if (endPosition > archiveSize) endPosition = archiveSize; getJobOutputRequest.SetRange(currentPosition, endPosition); GetJobOutputResponse getJobOutputResponse = client.GetJobOutput(getJobOutputRequest); using (Stream webStream = getJobOutputResponse.Body) { CopyStream(webStream, fileToSave); } currentPosition += partSize; } while (currentPosition < archiveSize); } } public static void CopyStream(Stream input, Stream output) { byte[] buffer = new byte[65536]; int length; while ((length = input.Read(buffer, 0, buffer.Length)) > 0) { output.Write(buffer, 0, length); } } } }