を使用した Amazon Glacier でのアーカイブのダウンロード AWS SDK for .NET - Amazon Glacier

このページは、Vaults と 2012 年の元の REST API を使用する Amazon Glacier サービスの既存のお客様専用です。

アーカイブストレージソリューションをお探しの場合は、Amazon Glacier Amazon S3、S3 Glacier Flexible Retrieval、S3 S3 Glacier Deep Archive の Amazon Glacier ストレージクラスを使用することをお勧めします。これらのストレージオプションの詳細については、Amazon Glacier ストレージクラス」を参照してください。

Amazon Glacier (元のスタンドアロンボールトベースのサービス) は、2025 年 12 月 15 日以降、既存の顧客に影響を与えずに新規顧客を受け入れなくなります。Amazon Glacier は、ボールトにデータを保存する独自の APIs を備えたスタンドアロンサービスであり、Amazon S3 および Amazon S3 Glacier ストレージクラスとは異なります。既存のデータは Amazon Glacier で無期限に安全でアクセス可能です。移行は必要ありません。低コストの長期アーカイブストレージの場合、 は 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

両方高レベル API と低レベル API.NET 用の Amazon SDK で提供されており、アーカイブをダウンロードする方法を提供します。

の高レベル API を使用したアーカイブのダウンロード AWS SDK for .NET

高レベル API の ArchiveTransferManager クラスには、アーカイブのダウンロードに使用できる Download メソッドが用意されています。

重要

-ArchiveTransferManagerクラスは、Amazon Simple Notification Service (Amazon SNS) トピックと、そのトピックにサブスクライブされている Amazon Simple Queue Service (Amazon SQS) キューを作成します。その後、アーカイブの取り出しジョブを開始し、使用可能にするアーカイブを探してキューをポーリングします。アーカイブが使用可能になると、ダウンロードが開始されます。取得時間に関する詳細については、「アーカイブの取り出しオプション」を参照してください。

例: の高レベル API を使用したアーカイブのダウンロード AWS SDK for .NET

次の C# コード例では、米国西部(オレゴン リージョン (examplevault) のボールト からアーカイブをダウンロードします。

この例を実行するための詳しい手順については、「コード例の実行」を参照してください。ここに示したコードは、既存のアーカイブ 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 ジョブを開始します。

    ダウンロードするアーカイブのアーカイブ ID や、Amazon Glacier がジョブ完了メッセージを投稿するオプションの Amazon SNS トピックなどのジョブ情報を指定するには、 InitiateJobRequest クラスのインスタンスを作成します。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 にリクエストできます。リクエストは、アーカイブの 1 MB から 2 MB の部分のみを準備するように 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 のチェックサムと比較します。

    オプションの範囲が指定されたアーカイブの取得ジョブの場合は、ジョブの説明を取得したときに取得する範囲のチェックサムが含まれます(SHA256TreeHash)。この値によって、後でダウンロードするバイト範囲全体の正確性を詳しく確認できます。たとえば、木構造ハッシュ可能なアーカイブ範囲を取得するジョブを開始してから、出力を複数のチャンクに分けてダウンロードし、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 (Amazon SNS) のトピックを設定する

    Amazon Glacier は、ジョブの完了後にこのトピックに通知を送信します。

  • Amazon Simple Queue Service (Amazon SQS) キューを設定する

    この例では、ポリシーをキューにアタッチして、Amazon SNS トピックでメッセージを投稿できるようにします。

  • 指定したアーカイブをダウンロードするジョブを開始します。

    この例では、ジョブリクエストで Amazon SNS トピックを指定し、Amazon Glacier がジョブの完了後にメッセージを送信できるようにします。

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