使用 AWS SDK for Java 在 Amazon S3 Glacier 中下載文件庫庫存 - Amazon S3 Glacier

此頁面僅適用於使用 Vault 和 REST API 2012 年原始版本的 S3 Glacier 服務的現有客戶。

如果您要尋找封存儲存解決方案,建議您在 Amazon S3、S3 Glacier S3 Instant RetrievalS3 Glacier Flexible Retrieval 和 S3 Glacier Deep Archive 中使用 S3 Glacier 儲存類別。若要進一步了解這些儲存選項,請參閱 Amazon S3 使用者指南 中的使用 S3 Glacier 儲存類別的 S3 Glacier 儲存類別和長期資料儲存Amazon S3 這些儲存類別使用 Amazon S3 API,適用於所有區域,並且可以在 Amazon S3 主控台中管理。它們提供 Storage Cost Analysis、Storage Lens、進階選用加密功能等功能。

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用 AWS SDK for Java 在 Amazon S3 Glacier 中下載文件庫庫存

以下是使用 AWS SDK for Java 低階 API 來擷取文件庫庫存的步驟。高階的 API 不支援擷取文件庫庫存。

  1. 建立 AmazonGlacierClient 類別的執行個體 (用戶端)。

    您需要指定文件庫所在的 AWS 區域。所有您使用此用戶端執行的操作均會套用到該 AWS 區域。

  2. 透過執行 initiateJob 方法來起始庫存擷取任務。

    透過提供 initiateJob 物件中的任務資訊來執行 InitiateJobRequest

    注意

    請注意,如果文件庫庫存尚未完成,便會傳回錯誤。Amazon S3 Glacier (S3 Glacier) 會每 24 小時定期為每個文件庫準備好庫存。

    S3 Glacier 會在回應中傳回任務 ID。該回應在 InitiateJobResult 類別的執行個體中可用。

    InitiateJobRequest initJobRequest = new InitiateJobRequest() .withVaultName("*** provide vault name ***") .withJobParameters( new JobParameters() .withType("inventory-retrieval") .withSNSTopic("*** provide SNS topic ARN ****") ); InitiateJobResult initJobResult = client.initiateJob(initJobRequest); String jobId = initJobResult.getJobId();
  3. 等候任務完成。

    您必須等到任務輸出準備好供您下載。如果您在文件庫上設定通知設定,或者在起始任務時指定 Amazon Simple Notification Service (Amazon SNS) 主題,則 S3 Glacier 會在完成任務後向該主題傳送訊息。

    您也可以透過呼叫 describeJob 方法來輪詢 S3 Glacier,以判斷任務完成狀態。不過,使用 Amazon SNS 主題進行通知是建議的方法。以下章節提供的程式碼使用適用於 S3 Glacier 的 Amazon SNS 來發布訊息。

  4. 透過執行 getJobOutput 方法下載任務輸出 (文件庫庫存資料)。

    您透過建立 GetJobOutputRequest 類別的執行個體來提供帳戶 ID、任務 ID 和文件庫名稱。如果您不提供帳戶 ID,則會使用與您提供來簽署請求之登入資料關聯的帳戶 ID。如需更多詳細資訊,請參閱 將 AWS SDK for Java 與 Amazon S3 Glacier 搭配使用

    S3 Glacier 傳回的輸出在 GetJobOutputResult 物件中可用。

    GetJobOutputRequest jobOutputRequest = new GetJobOutputRequest() .withVaultName("*** provide vault name ***") .withJobId("*** provide job ID ***"); GetJobOutputResult jobOutputResult = client.getJobOutput(jobOutputRequest); // jobOutputResult.getBody(); provides the output stream.

注意

如需與任務相關的底層 REST API 的資訊,請參閱 任務操作

範例:使用適用於 Java 的 Amazon 開發套件擷取文件庫庫存

以下 Java 程式碼範例將擷取指定文件庫的文件庫清查。

範例會執行下列任務:

  • 建立 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.BufferedReader; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; 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.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 AmazonGlacierDownloadInventoryWithSQSPolling { 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("Inventory 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("inventory-retrieval") .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.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(); 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); FileWriter fstream = new FileWriter(fileName); BufferedWriter out = new BufferedWriter(fstream); BufferedReader in = new BufferedReader(new InputStreamReader(getJobOutputResult.getBody())); String inputLine; try { while ((inputLine = in.readLine()) != null) { out.write(inputLine); } }catch(IOException e) { throw new AmazonClientException("Unable to save archive", e); }finally{ try {in.close();} catch (Exception e) {} try {out.close();} catch (Exception e) {} } System.out.println("Retrieved inventory to " + fileName); } private static void cleanUp() { snsClient.unsubscribe(new UnsubscribeRequest(snsSubscriptionARN)); snsClient.deleteTopic(new DeleteTopicRequest(snsTopicARN)); sqsClient.deleteQueue(new DeleteQueueRequest(sqsQueueURL)); } }