此頁面僅適用於使用 Vault 和 REST API 2012 年原始版本的 S3 Glacier 服務的現有客戶。
如果您要尋找封存儲存解決方案,建議您在 Amazon S3、S3 Glacier S3 Instant Retrieval、S3 Glacier Flexible Retrieval 和 S3 Glacier Deep Archive 中使用 S3 Glacier 儲存類別。若要進一步了解這些儲存選項,請參閱 Amazon S3
本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
使用 AWS SDK for Java 下載 Amazon S3 Glacier 中的封存
適用於 Java 的 Amazon 開發套件提供的高階和低階 API 都提供了下載封存的方法。
使用 AWS SDK for Java 的高階 API 下載封存
高階 API 的 ArchiveTransferManager
類別提供可用來下載封存的 download
方法。
重要
此 ArchiveTransferManager
類別會建立 Amazon Simple Notification Service (Amazon SNS) 主題,以及訂閱該主題的 Amazon Simple Queue Service (Amazon SQS) 佇列。然後啟動封存擷取任務並輪詢佇列以使封存可用。封存可用時,就會開始下載。如需封存擷取時間的詳細資訊,請參閱 封存擷取選項。
範例:使用 AWS SDK for Java 的高階 API 下載封存
以下 Java 程式碼範例從美國西部 (奧勒岡) 區域 (us-west-2
) 中的文件庫 (examplevault
) 下載封存。
如需執行此範例的逐步說明,請參閱 使用 Eclipse 執行 Amazon S3 Glacier 的 Java 範例。您需要更新程式碼,如所示之在現有的封存 ID 以及欲儲存下載封存的本機檔案路徑 。
import java.io.File; import java.io.IOException; import com.amazonaws.auth.profile.ProfileCredentialsProvider; import com.amazonaws.services.glacier.AmazonGlacierClient; import com.amazonaws.services.glacier.transfer.ArchiveTransferManager; import com.amazonaws.services.sns.AmazonSNSClient; import com.amazonaws.services.sqs.AmazonSQSClient; public class ArchiveDownloadHighLevel { public static String vaultName = "examplevault"; public static String archiveId = "*** provide archive ID ***"; public static String downloadFilePath = "*** provide location to download archive ***"; public static AmazonGlacierClient glacierClient; public static AmazonSQSClient sqsClient; public static AmazonSNSClient snsClient; public static void main(String[] args) throws IOException { ProfileCredentialsProvider credentials = new ProfileCredentialsProvider(); glacierClient = new AmazonGlacierClient(credentials); sqsClient = new AmazonSQSClient(credentials); snsClient = new AmazonSNSClient(credentials); glacierClient.setEndpoint("glacier.us-west-2.amazonaws.com"); sqsClient.setEndpoint("sqs.us-west-2.amazonaws.com"); snsClient.setEndpoint("sns.us-west-2.amazonaws.com"); try { ArchiveTransferManager atm = new ArchiveTransferManager(glacierClient, sqsClient, snsClient); atm.download(vaultName, archiveId, new File(downloadFilePath)); System.out.println("Downloaded file to " + downloadFilePath); } catch (Exception e) { System.err.println(e); } } }
使用 AWS SDK for Java 的低階 API 下載封存
以下是使用 AWS SDK for Java 低階 API 來擷取文件庫庫存的步驟。
-
建立
AmazonGlacierClient
類別的執行個體 (用戶端)。您需要指定要從中下載封存的 AWS 區域。所有您使用此用戶端執行的操作均會套用到該 AWS 區域。
-
執行
archive-retrieval
方法以啟動initiateJob
任務。透過建立
InitiateJobRequest
類別的執行個體來提供任務資訊,例如要下載之封存的封存 ID,以及希望 Amazon S3 Glacier (S3 Glacier) 發佈任務完成訊息的選用 Amazon SNS 主題。S3 Glacier 會在回應中傳回任務 ID。該回應在InitiateJobResult
類別的執行個體中可用。JobParameters jobParameters = new JobParameters() .withArchiveId("*** provide an archive id ***") .withDescription("archive retrieval") .withRetrievalByteRange("*** provide a retrieval range***") // optional .withType("archive-retrieval"); InitiateJobResult initiateJobResult = client.initiateJob(new InitiateJobRequest() .withJobParameters(jobParameters) .withVaultName(vaultName)); String jobId = initiateJobResult.getJobId();
您可以選擇指定位元組範圍來請求 S3 Glacier,以便僅準備封存的一部分。例如,您可以透過新增以下陳述式,來請求 S3 Glacier 僅準備封存的 1 MB 到 2 MB 部分,從而更新上述請求。
int ONE_MEG = 1048576; String retrievalByteRange = String.format("%s-%s", ONE_MEG, 2*ONE_MEG -1); JobParameters jobParameters = new JobParameters() .withType("archive-retrieval") .withArchiveId(archiveId) .withRetrievalByteRange(retrievalByteRange) .withSNSTopic(snsTopicARN); InitiateJobResult initiateJobResult = client.initiateJob(new InitiateJobRequest() .withJobParameters(jobParameters) .withVaultName(vaultName)); String jobId = initiateJobResult.getJobId();
-
等候任務完成。
您必須等到任務輸出準備好供您下載。如果您在文件庫上設定識別 Amazon Simple Notification Service (Amazon SNS) 主題的通知設定,或者在啟動任務時指定 Amazon SNS 主題,則 S3 Glacier 會在完成任務後向該主題傳送訊息。
您也可以透過呼叫
describeJob
方法來輪詢 S3 Glacier,以判斷任務完成狀態。雖然,使用 Amazon SNS 主題進行通知是建議的方法。 -
透過執行
getJobOutput
方法下載任務輸出 (封存資料)。透過建立
GetJobOutputRequest
類別的執行個體來提供請求資訊,如任務 ID 和文件庫名稱。S3 Glacier 傳回的輸出在GetJobOutputResult
物件中可用。GetJobOutputRequest jobOutputRequest = new GetJobOutputRequest() .withJobId("*** provide a job ID ***") .withVaultName("*** provide a vault name ****"); GetJobOutputResult jobOutputResult = client.getJobOutput(jobOutputRequest); // jobOutputResult.getBody() // Provides the input stream.
上述程式碼片段下載整個任務的輸出。您可以選擇只擷取輸出的一部分,或透過指定
GetJobOutputRequest
中的位元組範圍以較小的區塊下載整個輸出。GetJobOutputRequest jobOutputRequest = new GetJobOutputRequest() .withJobId("*** provide a job ID ***") .withRange("bytes=0-1048575") // Download only the first 1 MB of the output. .withVaultName("*** provide a vault name ****");
為了回應
GetJobOutput
呼叫,如果滿足某些條件,S3 Glacier 將傳回下載資料部分的檢查總和。如需更多詳細資訊,請參閱 下載資料時接收檢查總和。為了驗證下載沒有錯誤,您可以計算用戶端的檢查總和,並將其與在回應中傳送的檢查總和 S3 Glacier 相比較。
對於指定可選範圍的封存擷取任務,當您取得任務說明時,它將包含您正在擷取的範圍的檢查總和 (SHA256TreeHash)。您可以使用此值進一步驗證稍後下載的整個位元組範圍的準確性。例如,如果啟動任務以擷取樹狀雜湊符合的封存範圍,然後以區塊的方式下載輸出,以便每個
GetJobOutput
請求傳回檢查總和,則可以計算在用戶端上下載的每個部分的檢查總和,然後計算樹狀雜湊。您可以將它與 S3 Glacier 傳回的檢查總和進行比較,以回應您的描述任務請求,以驗證您下載的整個位元組範圍與存放在 S3 Glacier 中的位元組範圍相同。如需運作範例,請參閱 範例 2:使用區塊中的 AWS SDK for Java下載輸出的低階 API 擷取封存 。
範例 1:使用 AWS SDK for Java 的低階 API 擷取封存
以下 Java 程式碼範例從指定的文件庫下載封存。任務完成後,該範例將在單一 getJobOutput
呼叫中下載整個輸出。如需有關以區塊形式下載輸出的範例,請參閱 範例 2:使用區塊中的 AWS SDK for Java下載輸出的低階 API 擷取封存 。
範例會執行下列任務:
-
建立 Amazon Simple Notification Service (Amazon SNS) 主題。
S3 Glacier 會在完成任務後向該主題傳送通知。
-
建立 Amazon Simple Queue Service (Amazon SQS) 佇列。
此範例將政策連接至佇列,以使 Amazon SNS 主題能夠發佈訊息到佇列。
-
起始任務以下載指定的封存。
在任務請求中,會指定所建立的 Amazon SNS 主題,因此,S3 Glacier 可以在完成任務後發布通知到主題。
-
定期檢查 Amazon SQS 佇列中是否有包含任務 ID 的訊息。
如果有訊息,剖析 JSON 並檢查任務是否順利完成。如果是,請下載封存。
-
透過刪除 Amazon SNS 主題和其建立的 Amazon SQS 佇列來清除。
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.util.HashMap; import java.util.List; import java.util.Map; import org.codehaus.jackson.JsonFactory; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.JsonParseException; import org.codehaus.jackson.JsonParser; import org.codehaus.jackson.map.ObjectMapper; import com.amazonaws.AmazonClientException; import com.amazonaws.auth.policy.Policy; import com.amazonaws.auth.policy.Principal; import com.amazonaws.auth.policy.Resource; import com.amazonaws.auth.policy.Statement; import com.amazonaws.auth.policy.Statement.Effect; import com.amazonaws.auth.policy.actions.SQSActions; import com.amazonaws.auth.profile.ProfileCredentialsProvider; import com.amazonaws.services.glacier.AmazonGlacierClient; import com.amazonaws.services.glacier.model.GetJobOutputRequest; import com.amazonaws.services.glacier.model.GetJobOutputResult; import com.amazonaws.services.glacier.model.InitiateJobRequest; import com.amazonaws.services.glacier.model.InitiateJobResult; import com.amazonaws.services.glacier.model.JobParameters; import com.amazonaws.services.sns.AmazonSNSClient; import com.amazonaws.services.sns.model.CreateTopicRequest; import com.amazonaws.services.sns.model.CreateTopicResult; import com.amazonaws.services.sns.model.DeleteTopicRequest; import com.amazonaws.services.sns.model.SubscribeRequest; import com.amazonaws.services.sns.model.SubscribeResult; import com.amazonaws.services.sns.model.UnsubscribeRequest; import com.amazonaws.services.sqs.AmazonSQSClient; import com.amazonaws.services.sqs.model.CreateQueueRequest; import com.amazonaws.services.sqs.model.CreateQueueResult; import com.amazonaws.services.sqs.model.DeleteQueueRequest; import com.amazonaws.services.sqs.model.GetQueueAttributesRequest; import com.amazonaws.services.sqs.model.GetQueueAttributesResult; import com.amazonaws.services.sqs.model.Message; import com.amazonaws.services.sqs.model.ReceiveMessageRequest; import com.amazonaws.services.sqs.model.SetQueueAttributesRequest; public class AmazonGlacierDownloadArchiveWithSQSPolling { public static String archiveId = "*** provide archive ID ****"; public static String vaultName = "*** provide vault name ***"; public static String snsTopicName = "*** provide topic name ***"; public static String sqsQueueName = "*** provide queue name ***"; public static String sqsQueueARN; public static String sqsQueueURL; public static String snsTopicARN; public static String snsSubscriptionARN; public static String fileName = "*** provide file name ***"; public static String region = "*** region ***"; public static long sleepTime = 600; public static AmazonGlacierClient client; public static AmazonSQSClient sqsClient; public static AmazonSNSClient snsClient; public static void main(String[] args) throws IOException { ProfileCredentialsProvider credentials = new ProfileCredentialsProvider(); client = new AmazonGlacierClient(credentials); client.setEndpoint("https://glacier." + region + ".amazonaws.com"); sqsClient = new AmazonSQSClient(credentials); sqsClient.setEndpoint("https://sqs." + region + ".amazonaws.com"); snsClient = new AmazonSNSClient(credentials); snsClient.setEndpoint("https://sns." + region + ".amazonaws.com"); try { setupSQS(); setupSNS(); String jobId = initiateJobRequest(); System.out.println("Jobid = " + jobId); Boolean success = waitForJobToComplete(jobId, sqsQueueURL); if (!success) { throw new Exception("Job did not complete successfully."); } downloadJobOutput(jobId); cleanUp(); } catch (Exception e) { System.err.println("Archive retrieval failed."); System.err.println(e); } } private static void setupSQS() { CreateQueueRequest request = new CreateQueueRequest() .withQueueName(sqsQueueName); CreateQueueResult result = sqsClient.createQueue(request); sqsQueueURL = result.getQueueUrl(); GetQueueAttributesRequest qRequest = new GetQueueAttributesRequest() .withQueueUrl(sqsQueueURL) .withAttributeNames("QueueArn"); GetQueueAttributesResult qResult = sqsClient.getQueueAttributes(qRequest); sqsQueueARN = qResult.getAttributes().get("QueueArn"); Policy sqsPolicy = new Policy().withStatements( new Statement(Effect.Allow) .withPrincipals(Principal.AllUsers) .withActions(SQSActions.SendMessage) .withResources(new Resource(sqsQueueARN))); Map<String, String> queueAttributes = new HashMap<String, String>(); queueAttributes.put("Policy", sqsPolicy.toJson()); sqsClient.setQueueAttributes(new SetQueueAttributesRequest(sqsQueueURL, queueAttributes)); } private static void setupSNS() { CreateTopicRequest request = new CreateTopicRequest() .withName(snsTopicName); CreateTopicResult result = snsClient.createTopic(request); snsTopicARN = result.getTopicArn(); SubscribeRequest request2 = new SubscribeRequest() .withTopicArn(snsTopicARN) .withEndpoint(sqsQueueARN) .withProtocol("sqs"); SubscribeResult result2 = snsClient.subscribe(request2); snsSubscriptionARN = result2.getSubscriptionArn(); } private static String initiateJobRequest() { JobParameters jobParameters = new JobParameters() .withType("archive-retrieval") .withArchiveId(archiveId) .withSNSTopic(snsTopicARN); InitiateJobRequest request = new InitiateJobRequest() .withVaultName(vaultName) .withJobParameters(jobParameters); InitiateJobResult response = client.initiateJob(request); return response.getJobId(); } private static Boolean waitForJobToComplete(String jobId, String sqsQueueUrl) throws InterruptedException, JsonParseException, IOException { Boolean messageFound = false; Boolean jobSuccessful = false; ObjectMapper mapper = new ObjectMapper(); JsonFactory factory = mapper.getJsonFactory(); while (!messageFound) { List<Message> msgs = sqsClient.receiveMessage( new ReceiveMessageRequest(sqsQueueUrl).withMaxNumberOfMessages(10)).getMessages(); if (msgs.size() > 0) { for (Message m : msgs) { JsonParser jpMessage = factory.createJsonParser(m.getBody()); JsonNode jobMessageNode = mapper.readTree(jpMessage); String jobMessage = jobMessageNode.get("Message").getTextValue(); JsonParser jpDesc = factory.createJsonParser(jobMessage); JsonNode jobDescNode = mapper.readTree(jpDesc); String retrievedJobId = jobDescNode.get("JobId").getTextValue(); String statusCode = jobDescNode.get("StatusCode").getTextValue(); if (retrievedJobId.equals(jobId)) { messageFound = true; if (statusCode.equals("Succeeded")) { jobSuccessful = true; } } } } else { Thread.sleep(sleepTime * 1000); } } return (messageFound && jobSuccessful); } private static void downloadJobOutput(String jobId) throws IOException { GetJobOutputRequest getJobOutputRequest = new GetJobOutputRequest() .withVaultName(vaultName) .withJobId(jobId); GetJobOutputResult getJobOutputResult = client.getJobOutput(getJobOutputRequest); InputStream input = new BufferedInputStream(getJobOutputResult.getBody()); OutputStream output = null; try { output = new BufferedOutputStream(new FileOutputStream(fileName)); byte[] buffer = new byte[1024 * 1024]; int bytesRead = 0; do { bytesRead = input.read(buffer); if (bytesRead <= 0) break; output.write(buffer, 0, bytesRead); } while (bytesRead > 0); } catch (IOException e) { throw new AmazonClientException("Unable to save archive", e); } finally { try {input.close();} catch (Exception e) {} try {output.close();} catch (Exception e) {} } System.out.println("Retrieved archive to " + fileName); } private static void cleanUp() { snsClient.unsubscribe(new UnsubscribeRequest(snsSubscriptionARN)); snsClient.deleteTopic(new DeleteTopicRequest(snsTopicARN)); sqsClient.deleteQueue(new DeleteQueueRequest(sqsQueueURL)); } }
範例 2:使用區塊中的 AWS SDK for Java下載輸出的低階 API 擷取封存
下列 Java 程式碼範例會從 S3 Glacier 擷取封存。該程式碼範例透過在 GetJobOutputRequest
物件中指定位元組範圍來下載區塊中的任務輸出。
import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.amazonaws.auth.policy.Policy; import com.amazonaws.auth.policy.Principal; import com.amazonaws.auth.policy.Resource; import com.amazonaws.auth.policy.Statement; import com.amazonaws.auth.policy.Statement.Effect; import com.amazonaws.auth.policy.actions.SQSActions; import com.amazonaws.auth.profile.ProfileCredentialsProvider; import com.amazonaws.services.glacier.AmazonGlacierClient; import com.amazonaws.services.glacier.TreeHashGenerator; import com.amazonaws.services.glacier.model.GetJobOutputRequest; import com.amazonaws.services.glacier.model.GetJobOutputResult; import com.amazonaws.services.glacier.model.InitiateJobRequest; import com.amazonaws.services.glacier.model.InitiateJobResult; import com.amazonaws.services.glacier.model.JobParameters; import com.amazonaws.services.sns.AmazonSNSClient; import com.amazonaws.services.sns.model.CreateTopicRequest; import com.amazonaws.services.sns.model.CreateTopicResult; import com.amazonaws.services.sns.model.DeleteTopicRequest; import com.amazonaws.services.sns.model.SubscribeRequest; import com.amazonaws.services.sns.model.SubscribeResult; import com.amazonaws.services.sns.model.UnsubscribeRequest; import com.amazonaws.services.sqs.AmazonSQSClient; import com.amazonaws.services.sqs.model.CreateQueueRequest; import com.amazonaws.services.sqs.model.CreateQueueResult; import com.amazonaws.services.sqs.model.DeleteQueueRequest; import com.amazonaws.services.sqs.model.GetQueueAttributesRequest; import com.amazonaws.services.sqs.model.GetQueueAttributesResult; import com.amazonaws.services.sqs.model.Message; import com.amazonaws.services.sqs.model.ReceiveMessageRequest; import com.amazonaws.services.sqs.model.SetQueueAttributesRequest; public class ArchiveDownloadLowLevelWithRange { public static String vaultName = "*** provide vault name ***"; public static String archiveId = "*** provide archive id ***"; public static String snsTopicName = "glacier-temp-sns-topic"; public static String sqsQueueName = "glacier-temp-sqs-queue"; public static long downloadChunkSize = 4194304; // 4 MB public static String sqsQueueARN; public static String sqsQueueURL; public static String snsTopicARN; public static String snsSubscriptionARN; public static String fileName = "*** provide file name to save archive to ***"; public static String region = "*** region ***"; public static long sleepTime = 600; public static AmazonGlacierClient client; public static AmazonSQSClient sqsClient; public static AmazonSNSClient snsClient; public static void main(String[] args) throws IOException { ProfileCredentialsProvider credentials = new ProfileCredentialsProvider(); client = new AmazonGlacierClient(credentials); client.setEndpoint("https://glacier." + region + ".amazonaws.com"); sqsClient = new AmazonSQSClient(credentials); sqsClient.setEndpoint("https://sqs." + region + ".amazonaws.com"); snsClient = new AmazonSNSClient(credentials); snsClient.setEndpoint("https://sns." + region + ".amazonaws.com"); try { setupSQS(); setupSNS(); String jobId = initiateJobRequest(); System.out.println("Jobid = " + jobId); long archiveSizeInBytes = waitForJobToComplete(jobId, sqsQueueURL); if (archiveSizeInBytes==-1) { throw new Exception("Job did not complete successfully."); } downloadJobOutput(jobId, archiveSizeInBytes); cleanUp(); } catch (Exception e) { System.err.println("Archive retrieval failed."); System.err.println(e); } } private static void setupSQS() { CreateQueueRequest request = new CreateQueueRequest() .withQueueName(sqsQueueName); CreateQueueResult result = sqsClient.createQueue(request); sqsQueueURL = result.getQueueUrl(); GetQueueAttributesRequest qRequest = new GetQueueAttributesRequest() .withQueueUrl(sqsQueueURL) .withAttributeNames("QueueArn"); GetQueueAttributesResult qResult = sqsClient.getQueueAttributes(qRequest); sqsQueueARN = qResult.getAttributes().get("QueueArn"); Policy sqsPolicy = new Policy().withStatements( new Statement(Effect.Allow) .withPrincipals(Principal.AllUsers) .withActions(SQSActions.SendMessage) .withResources(new Resource(sqsQueueARN))); Map<String, String> queueAttributes = new HashMap<String, String>(); queueAttributes.put("Policy", sqsPolicy.toJson()); sqsClient.setQueueAttributes(new SetQueueAttributesRequest(sqsQueueURL, queueAttributes)); } private static void setupSNS() { CreateTopicRequest request = new CreateTopicRequest() .withName(snsTopicName); CreateTopicResult result = snsClient.createTopic(request); snsTopicARN = result.getTopicArn(); SubscribeRequest request2 = new SubscribeRequest() .withTopicArn(snsTopicARN) .withEndpoint(sqsQueueARN) .withProtocol("sqs"); SubscribeResult result2 = snsClient.subscribe(request2); snsSubscriptionARN = result2.getSubscriptionArn(); } private static String initiateJobRequest() { JobParameters jobParameters = new JobParameters() .withType("archive-retrieval") .withArchiveId(archiveId) .withSNSTopic(snsTopicARN); InitiateJobRequest request = new InitiateJobRequest() .withVaultName(vaultName) .withJobParameters(jobParameters); InitiateJobResult response = client.initiateJob(request); return response.getJobId(); } private static long waitForJobToComplete(String jobId, String sqsQueueUrl) throws InterruptedException, JsonParseException, IOException { Boolean messageFound = false; Boolean jobSuccessful = false; long archiveSizeInBytes = -1; ObjectMapper mapper = new ObjectMapper(); JsonFactory factory = mapper.getFactory(); while (!messageFound) { List<Message> msgs = sqsClient.receiveMessage( new ReceiveMessageRequest(sqsQueueUrl).withMaxNumberOfMessages(10)).getMessages(); if (msgs.size() > 0) { for (Message m : msgs) { JsonParser jpMessage = factory.createJsonParser(m.getBody()); JsonNode jobMessageNode = mapper.readTree(jpMessage); String jobMessage = jobMessageNode.get("Message").textValue(); JsonParser jpDesc = factory.createJsonParser(jobMessage); JsonNode jobDescNode = mapper.readTree(jpDesc); String retrievedJobId = jobDescNode.get("JobId").textValue(); String statusCode = jobDescNode.get("StatusCode").textValue(); archiveSizeInBytes = jobDescNode.get("ArchiveSizeInBytes").longValue(); if (retrievedJobId.equals(jobId)) { messageFound = true; if (statusCode.equals("Succeeded")) { jobSuccessful = true; } } } } else { Thread.sleep(sleepTime * 1000); } } return (messageFound && jobSuccessful) ? archiveSizeInBytes : -1; } private static void downloadJobOutput(String jobId, long archiveSizeInBytes) throws IOException { if (archiveSizeInBytes < 0) { System.err.println("Nothing to download."); return; } System.out.println("archiveSizeInBytes: " + archiveSizeInBytes); FileOutputStream fstream = new FileOutputStream(fileName); long startRange = 0; long endRange = (downloadChunkSize > archiveSizeInBytes) ? archiveSizeInBytes -1 : downloadChunkSize - 1; do { GetJobOutputRequest getJobOutputRequest = new GetJobOutputRequest() .withVaultName(vaultName) .withRange("bytes=" + startRange + "-" + endRange) .withJobId(jobId); GetJobOutputResult getJobOutputResult = client.getJobOutput(getJobOutputRequest); BufferedInputStream is = new BufferedInputStream(getJobOutputResult.getBody()); byte[] buffer = new byte[(int)(endRange - startRange + 1)]; System.out.println("Checksum received: " + getJobOutputResult.getChecksum()); System.out.println("Content range " + getJobOutputResult.getContentRange()); int totalRead = 0; while (totalRead < buffer.length) { int bytesRemaining = buffer.length - totalRead; int read = is.read(buffer, totalRead, bytesRemaining); if (read > 0) { totalRead = totalRead + read; } else { break; } } System.out.println("Calculated checksum: " + TreeHashGenerator.calculateTreeHash(new ByteArrayInputStream(buffer))); System.out.println("read = " + totalRead); fstream.write(buffer); startRange = startRange + (long)totalRead; endRange = ((endRange + downloadChunkSize) > archiveSizeInBytes) ? archiveSizeInBytes : (endRange + downloadChunkSize); is.close(); } while (endRange <= archiveSizeInBytes && startRange < archiveSizeInBytes); fstream.close(); System.out.println("Retrieved file to " + fileName); } private static void cleanUp() { snsClient.unsubscribe(new UnsubscribeRequest(snsSubscriptionARN)); snsClient.deleteTopic(new DeleteTopicRequest(snsTopicARN)); sqsClient.deleteQueue(new DeleteQueueRequest(sqsQueueURL)); } }