를 사용하여 Amazon Glacier에서 아카이브 다운로드 AWS SDK for .NET - Amazon Glacier

이 페이지는 볼트와 2012년의 원래 REST API를 사용하는 Amazon Glacier 서비스의 기존 고객에게만 해당됩니다.

아카이브 스토리지 솔루션을 찾고 있다면 Amazon Glacier Amazon S3, S3 Glacier Flexible Retrieval 및 S3S3 Glacier Deep Archive의 Amazon Glacier 스토리지 클래스를 사용하는 것이 좋습니다. 이러한 스토리지 옵션에 대한 자세한 내용은 Amazon Glacier 스토리지 클래스를 참조하세요.

Amazon Glacier(기존 독립 실행형 볼트 기반 서비스)는 2025년 12월 15일부터 기존 고객에게 영향을 주지 않고 더 이상 신규 고객을 받지 않습니다. Amazon Glacier는 데이터를 볼트에 저장하고 Amazon S3 및 Amazon S3 Glacier 스토리지 클래스와 구별되는 자체 APIs가 있는 독립 실행형 서비스입니다. 기존 데이터는 Amazon Glacier에서 무기한으로 안전하고 액세스할 수 있습니다. 마이그레이션이 필요하지 않습니다. 저비용 장기 아카이브 스토리지의 경우는 S3 버킷 기반 API, 전체 가용성, 저렴한 비용 및 서비스 통합을 통해 우수한 고객 경험을 제공하는 Amazon S3 Glacier 스토리지 클래스를 AWS 권장합니다. S3 APIs AWS 리전 AWS 향상된 기능을 원하는 경우 Amazon Glacier 볼트에서 Amazon S3 Glacier 스토리지 클래스로 데이터를 전송하기 위한 솔루션 지침을 사용하여 Amazon S3 Glacier 스토리지 클래스로 마이그레이션하는 것이 좋습니다. AWS Amazon Glacier Amazon S3

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

를 사용하여 Amazon Glacier에서 아카이브 다운로드 AWS SDK for .NET

Amazon SDK for .NET에서 제공하는 하이레벨 및 로우레벨 API 둘 모두는 아카이브를 다운로드하는 방법을 제공합니다.

의 상위 수준 API를 사용하여 아카이브 다운로드 AWS SDK for .NET

고레벨 API의 ArchiveTransferManager 클래스는 아카이브를 다운로드하는 데 사용할 수 있는 Download 메서드를 제공합니다.

중요

ArchiveTransferManager 클래스는 Amazon Simple Notification Service(SNS) 토픽 및 해당 토픽을 구독하는 Amazon Simple Queue Service(Amazon SQS) 대기열을 생성합니다. 그런 다음 아카이브 가져오기 작업을 시작하고 아카이브를 사용할 수 있도록 대기열을 폴링합니다. 아카이브를 사용할 수 있게 되면 다운로드가 시작됩니다. 검색 시간에 대한 자세한 내용은 아카이브 검색 옵션 단원을 참조하십시오.

예:의 상위 수준 API를 사용하여 아카이브 다운로드 AWS SDK for .NET

다음은 미국 서부(오레곤) 리전의 볼트(examplevault)에서 아카이브를 다운로드하는 C# 코드 예시입니다.

이 예제의 실행 방법에 대한 단계별 지침은 코드 예제 실행 단원을 참조하십시오. 코드는 기존 아카이브 ID와 다운로드한 아카이브를 저장할 로컬 파일 경로를 사용해 아래와 같이 업데이트해야 합니다.

using System; using Amazon.Glacier; using Amazon.Glacier.Transfer; using Amazon.Runtime; namespace glacier.amazon.com.rproxy.govskope.ca.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); } } } }

의 하위 수준 API를 사용하여 아카이브 다운로드 AWS SDK for .NET

다음은의 하위 수준 API를 사용하여 Amazon Glacier(Amazon Glacier) 아카이브를 다운로드하는 단계입니다 AWS SDK for .NET.

  1. AmazonGlacierClient 클래스(클라이언트)의 인스턴스를 만듭니다.

    아카이브를 다운로드할 AWS 리전을 지정해야 합니다. 이 클라이언트를 사용하여 수행하는 모든 작업은 해당 AWS 리전에 적용됩니다.

  2. archive-retrieval 메서드를 실행하여 InitiateJob 작업을 시작합니다.

    InitiateJobRequest 클래스의 인스턴스를 생성하여 다운로드하려는 아카이브의 아카이브 ID 및 Amazon Glacier가 작업 완료 메시지를 게시할 선택적 Amazon SNS 주제와 같은 작업 정보를 제공합니다. Amazon Glacier는 응답으로 작업 ID를 반환합니다. 이 응답은 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;

    선택적으로 바이트 범위를 지정하여 다음 요청과 같이 Amazon Glacier가 아카이브의 일부만 준비하도록 요청할 수 있습니다. 요청은 아카이브의 1MB~2MB 부분만 준비하도록 Amazon Glacier를 지정합니다.

    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. 작업이 완료될 때까지 기다립니다.

    작업 출력을 다운로드할 수 있을 때까지 기다려야 합니다. 볼트에서 Amazon Simple Notification Service(Amazon SNS) 주제를 식별하는 알림 구성을 설정했거나 작업을 시작할 때 Amazon SNS 주제를 지정한 경우 Amazon Glacier는 작업을 완료한 후 해당 주제에 메시지를 보냅니다. 다음 섹션에 제공된 코드 예제에서는 Amazon Glacier용 Amazon SNS를 사용하여 메시지를 게시합니다. Amazon Glacier

    DescribeJob 메서드를 호출하여 작업 완료 상태를 확인하여 Amazon Glacier를 폴링할 수도 있습니다. 하지만 Amazon SNS 토픽의 알림을 사용해 식별하는 방법이 권장됩니다.

  4. GetJobOutput 메서드를 실행하여 작업 출력(아카이브 데이터)을 다운로드합니다.

    GetJobOutputRequest 클래스 인스턴스를 생성하여 작업 ID, 볼트 이름 등 요청 정보를 입력합니다. Amazon Glacier가 반환하는 출력은 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); } }

    위의 코드 조각은 전체 작업 출력을 다운로드합니다. 옵션으로 GetJobOutputRequest에서 바이트 범위를 지정하여 출력 일부만 가져오거나 전체 출력을 더 작은 청크 단위로 나누어 다운로드할 수 있습니다.

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

    GetJobOutput 호출에 대한 응답으로 Amazon Glacier는 특정 조건이 충족되는 경우 다운로드한 데이터의 부분에 대한 체크섬을 반환합니다. 자세한 내용은 데이터 다운로드 시 체크섬 수신 단원을 참조하십시오.

    다운로드에 오류가 없는지 확인하기 위해 클라이언트 측에서 체크섬을 계산하여 응답으로 전송된 체크섬 Amazon Glacier와 비교할 수 있습니다.

    옵션으로 범위를 지정하여 아카이브를 가져오는 작업에서는 작업 설명을 다운로드할 때 가져오는 범위에 대한 체크섬(SHA256 트리-해시)도 포함됩니다. 이 체크섬 값은 나중에 다운로드하는 전체 바이트 범위의 정확성을 검증하는 데 사용할 수 있습니다. 예를 들어 트리-해시로 정렬된 아카이브 범위를 가져오는 작업을 시작하면서 GetJobOutput 요청이 각각 체크섬을 반환할 수 있도록 청크 단위로 출력을 다운로드하는 경우에는 클라이언트 측에서 다운로드하는 개별 데이터의 체크섬을 계산하고 나서 트리 해시를 계산할 수 있습니다. 작업 설명 요청에 대한 응답으로 Amazon Glacier가 반환하는 체크섬과 비교하여 다운로드한 전체 바이트 범위가 Amazon Glacier에 저장된 바이트 범위와 동일한지 확인할 수 있습니다.

    사용 가능한 예제는 예제 2:의 하위 수준 API를 사용하여 아카이브 검색 AWS SDK for .NET- 청크 단위로 출력 다운로드를 참조하세요.

예제 1:의 하위 수준 API를 사용하여 아카이브 검색 AWS SDK for .NET

다음은 지정된 볼트에서 아카이브를 다운로드하는 C# 코드 예제입니다. 작업을 마치면 GetJobOutput 호출 한 번으로 전체 출력을 다운로드합니다. 출력을 청크 단위로 다운로드하는 예제는 예제 2:의 하위 수준 API를 사용하여 아카이브 검색 AWS SDK for .NET- 청크 단위로 출력 다운로드 단원을 참조하십시오.

이 예에서는 다음과 같은 작업을 수행합니다.

  • Amazon Simple Notification Service(SNS) 토픽 설정

    Amazon Glacier는 작업을 완료한 후이 주제에 알림을 보냅니다.

  • Amazon Simple Queue Service(Amazon SQS) 대기열을 설정합니다.

    아래 예시는 Amazon SNS 토픽이 메시지를 게시할 수 있도록 대기열에 정책을 연결합니다.

  • 지정된 아카이브의 다운로드 작업을 시작합니다.

    작업 요청에서이 예제는 Amazon Glacier가 작업을 완료한 후 메시지를 보낼 수 있도록 Amazon SNS 주제를 지정합니다.

  • Amazon SQS 대기열의 메시지를 주기적으로 확인합니다.

    메시지가 있으면 JSON 구문을 분석하여 작업이 성공적으로 완료되었는지 확인합니다. 성공적으로 완료되었으면 아카이브를 다운로드합니다. 아래 코드 예제에서는 JSON.NET 라이브러리(JSON.NET 참조)를 사용하여 JSON 구분을 분석합니다.

  • Amazon SNS 토픽과 토픽이 생성한 Amazon SQS 대기열을 삭제하여 정리합니다.

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.rproxy.govskope.ca.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\",&TCX5-2025-waiver;" + " \"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); } } } }

예제 2:의 하위 수준 API를 사용하여 아카이브 검색 AWS SDK for .NET- 청크 단위로 출력 다운로드

다음 C# 코드 예제는 Amazon Glacier에서 아카이브를 검색합니다. 이번 코드 예제는 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.rproxy.govskope.ca.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\",&TCX5-2025-waiver;" + " \"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); } } } }