

 **此頁面僅適用於使用 Vaults 和 2012 年原始 REST API 的 Amazon Glacier 服務的現有客戶。**

如果您要尋找封存儲存解決方案，建議您在 Amazon Glacier Instant Retrieval、S3 Glacier Flexible Retrieval 和 S3 Glacier Deep Archive 中使用 Amazon Glacier 儲存類別。 Amazon S3 若要進一步了解這些儲存選項，請參閱 [Amazon Glacier 儲存類別](https://aws.amazon.com/s3/storage-classes/glacier/)。

Amazon Glacier （原始獨立保存庫型服務） 不再接受新客戶。Amazon Glacier 是一項獨立服務，具有自己的 APIs，可將資料存放在保存庫中，並與 Amazon S3 和 Amazon S3 Glacier 儲存類別不同。您現有的資料將在 Amazon Glacier 中無限期保持安全且可存取。不需要遷移。對於低成本、長期的封存儲存， AWS 建議使用 [Amazon S3 Glacier 儲存類別](https://aws.amazon.com/s3/storage-classes/glacier/)，透過 S3 儲存貯體型 APIs、完整 AWS 區域 可用性、降低成本 AWS 和服務整合，提供卓越的客戶體驗。如果您想要增強功能，請考慮使用我們的解決方案指南，將資料從 Amazon S3 Glacier 保存庫傳輸至 Amazon S3 Glacier 儲存類別，以遷移至 Amazon S3 Glacier 儲存類別。 [AWS Amazon Glacier Amazon S3 ](https://aws.amazon.com/solutions/guidance/data-transfer-from-amazon-s3-glacier-vaults-to-amazon-s3/)

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

# 在 Amazon Glacier 中下載保存庫庫存
<a name="vault-inventory"></a>

將第一個封存上傳至保存庫後，Amazon Glacier (Amazon Glacier) 會自動建立保存庫庫存，然後大約每天更新一次。Amazon Glacier 建立第一個庫存後，通常需要半天到一天的時間才能擷取該庫存。您可以使用下列兩個步驟從 Amazon Glacier 擷取保存庫庫存：

 

1. 使用 [啟動任務 (POST 任務)](api-initiate-job-post.md) 操作啟動庫存擷取任務。
**重要**  
資料擷取政策可能導致啟動擷取作業請求失敗，並出現 `PolicyEnforcedException` 例外狀況。如需有關資料擷取政策的詳細資訊，請參閱 [Amazon Glacier 資料擷取政策](data-retrieval-policy.md)。如需 `PolicyEnforcedException` 例外狀況的詳細資訊，請參閱 [錯誤回應](api-error-responses.md)。

1. 任務完成後，使用 [「取得任務輸出」 (GET 輸出)](api-job-output-get.md) 操作下載位元組。

例如，擷取存檔或文件庫清查要求您先啟動擷取作業。以非同步方式執行工作請求。當您起始檢索任務時，Amazon Glacier 會建立任務，並在回應中傳回任務 ID。當 Amazon Glacier 完成工作時，您可以取得工作輸出、封存位元組或保存庫庫存資料。

必須完成任務，才能取得其輸出。若要判斷任務的狀態，您有下列選項：

 
+ **等待任務完成通知**—您可以指定 Amazon Simple Notification Service (Amazon SNS) 主題，Amazon Glacier 可以在任務完成後發佈通知。您可以使用以下方法指定此 Amazon SNS 主題：
  + 為每個工作指定 Amazon SNS 主題。

    啟動工作時，需選擇指定 Amazon SNS 主題。
  + 在文件庫上設定通知組態。

    您可以為保存庫中的特定事件設定通知設定 (請參閱 [在 Amazon Glacier 中設定保存庫通知](configuring-notifications.md))。只要發生特定事件，Amazon Glacier 就會傳送訊息至指定的 SNS 主題。

  如果您在保存庫上設定了通知組態，且在啟動任務時也指定了 Amazon SNS 主題，Amazon Glacier 會將任務完成訊息傳送至這兩個主題。

  您可以將 SNS 主題設定為透過電子郵件通知您，或者將訊息儲存在應用程式可以輪詢的 Amazon Simple Queue Service (Amazon SQS) 中。當訊息出現在佇列中時，您可以檢查任務是否順利完成，然後下載任務的輸出。
+ **明確請求任務資訊**—Amazon Glacier 也提供描述任務操作 ([描述任務 (GET JobID)](api-describe-job-get.md))，可讓您輪詢任務資訊。您可以定期發送此請求以獲取任務資訊。但是，使用 Amazon SNS 通知是建議的選項。

 

**注意**  
您透過 SNS 通知取得的資訊，與您呼叫描述任務所取得的資訊相同。

**Topics**
+ [關於庫存](#vault-inventory-about)
+ [使用 在 Amazon Glacier 中下載保存庫庫存 適用於 Java 的 AWS SDK](retrieving-vault-inventory-java.md)
+ [使用 在 Amazon Glacier 中下載保存庫庫存 適用於 .NET 的 AWS SDK](retrieving-vault-inventory-sdk-dotnet.md)
+ [使用 REST API下載文件庫清查](retrieving-vault-inventory-rest-api.md)
+ [使用 在 Amazon Glacier 中下載保存庫庫存 AWS Command Line Interface](retrieving-vault-inventory-cli.md)

## 關於庫存
<a name="vault-inventory-about"></a>

Amazon Glacier 每天至少更新一次保存庫庫存，從您第一次將封存上傳至保存庫的那一天開始。如果從上次清查以來，沒有新增或刪除文件庫的存檔，則清查日期不會更新。當您啟動保存庫庫存的任務時，Amazon Glacier 會傳回其產生的最後一個庫存，這是point-in-time快照，而不是即時資料。請注意，Amazon Glacier 為保存庫建立第一個庫存後，通常需要半天到最多一天的時間，才能擷取該庫存。

 您可能沒有發現為每個存檔上傳擷取文件庫清查的好處。不過，假設您在用戶端維護資料庫，關聯您上傳至 Amazon Glacier 之封存的相關中繼資料。然後，您可能會發現文件庫清查的好處，可以視需要在資料庫中使用實際的文件庫清查來調節資訊。您可以透過篩選存檔建立日期或設定配額來限制擷取到的清查項目數量。如需有關限制庫存擷取的詳細資訊，請參閱 [庫存擷取範圍](api-initiate-job-post.md#api-initiate-job-post-vault-inventory-list-filtering)。

您可以以逗號分隔值 (CSV) 或 JSON 兩種格式傳回庫存。您可以選擇指定啟動庫存任務時的格式。預設格式是 JSON。如需有關庫存任務輸出中傳回的資料欄位的詳細資訊，請參閱[回應內文](api-job-output-get.md#api-job-output-get-responses-elements)取得任務輸出 API* 的 *。

# 使用 在 Amazon Glacier 中下載保存庫庫存 適用於 Java 的 AWS SDK
<a name="retrieving-vault-inventory-java"></a>

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

 

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

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

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

   透過提供 `initiateJob` 物件中的工作資訊來執行 `InitiateJobRequest`。
**注意**  
請注意，如果保存庫庫存尚未完成，便會傳回錯誤。Amazon Glacier (Amazon Glacier) 每 24 小時定期為每個保存庫準備清查。

   Amazon 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();
   ```

1. 等候 工作完成。

   您必須等到任務輸出準備好供您下載。如果您已在保存庫上設定通知組態，或在啟動任務時指定 Amazon Simple Notification Service (Amazon SNS) 主題，Amazon Glacier 會在完成任務後傳送訊息至主題。

   您也可以呼叫 `describeJob`方法來輪詢 Amazon Glacier，以判斷任務完成狀態。不過，使用 Amazon SNS 主題進行通知是建議的方法。下一節中提供的程式碼範例使用 Amazon SNS for Amazon Glacier 來發佈訊息。

    

1. 透過執行 `getJobOutput` 方法下載工作輸出 (保存庫庫存資料)。

   您透過建立 `GetJobOutputRequest` 類別的執行個體來提供帳戶 ID、任務 ID 和文件庫名稱。如果您不提供帳戶 ID，則會使用與您提供來簽署請求之登入資料關聯的帳戶 ID。如需詳細資訊，請參閱[適用於 Java 的 AWS SDK 搭配 Amazon Glacier 使用](using-aws-sdk-for-java.md)。

   Amazon 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 的資訊，請參閱 [任務操作](job-operations.md)。

## 範例：使用適用於 Java 的 Amazon 開發套件擷取保存庫庫存
<a name="retrieving-vault-inventory-java-example"></a>

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

範例會執行下列任務：
+ 建立 Amazon Simple Notification Service (Amazon SNS) 主題。

  Amazon Glacier 會在完成任務後傳送通知至此主題。
+ 建立 Amazon Simple Queue Service (Amazon SQS) 佇列。

  此範例將政策連接至佇列，以使 Amazon SNS 主題能夠發佈訊息到佇列。
+ 起始任務以下載指定的封存。

  在任務請求中，指定已建立的 Amazon SNS 主題，以便 Amazon 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));
    }
}
```

# 使用 在 Amazon Glacier 中下載保存庫庫存 適用於 .NET 的 AWS SDK
<a name="retrieving-vault-inventory-sdk-dotnet"></a>

以下是使用 適用於 .NET 的 AWS SDK低階 API 來擷取保存庫庫存的步驟。高階的 API 不支援擷取保存庫庫存。

 

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

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

1. 透過執行 `InitiateJob` 方法來起始庫存擷取任務。

   您可以在 `InitiateJobRequest` 物件中提供工作資訊。Amazon Glacier (Amazon Glacier) 會傳回任務 ID 以回應。該回應在 `InitiateJobResponse` 類別的執行個體中可用。

    

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

1. 等候 工作完成。

   您必須等到任務輸出準備好供您下載。如果您已在識別 Amazon Simple Notification Service (Amazon SNS) 主題的保存庫上設定通知組態，或在啟動任務時指定 Amazon SNS 主題，Amazon Glacier 會在任務完成後傳送訊息至該主題。下一節中提供的程式碼範例使用 Amazon SNS for Amazon Glacier 來發佈訊息。

   您也可以呼叫 `DescribeJob`方法來輪詢 Amazon Glacier，以判斷任務完成狀態。雖然，使用 Amazon SNS 主題進行通知是建議的方法。

1. 透過執行 `GetJobOutput` 方法下載工作輸出 (保存庫庫存資料)。

   透過建立 `GetJobOutputRequest` 類別的執行個體來提供帳戶 ID、保存庫名稱和工作 ID 資訊。如果您不提供帳戶 ID，則會使用與您提供來簽署請求之登入資料關聯的帳戶 ID。如需詳細資訊，請參閱[適用於 .NET 的 AWS SDK 搭配 Amazon Glacier 使用](using-aws-sdk-for-dot-net.md)。

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

    
**注意**  
如需與任務相關的底層 REST API 的資訊，請參閱 [任務操作](job-operations.md)。

## 範例：使用 的低階 API 擷取保存庫庫存 適用於 .NET 的 AWS SDK
<a name="creating-vaults-sdk-dotnet-example-inventory"></a>

以下 C\$1 程式碼範例將擷取指定保存庫的保存庫庫存。

範例會執行下列任務：

 
+ 設定 Amazon SNS 主題。

  Amazon Glacier 會在完成任務後傳送通知至此主題。
+ 設定 Amazon SQS 佇列。

  此範例將政策連接至佇列，以使 Amazon SNS 主題能夠發佈訊息。
+ 啟動任務以下載指定的封存。

  在任務請求中，範例會指定 Amazon SNS 主題，以便 Amazon Glacier 在完成任務後傳送訊息。
+ 定期檢查 Amazon SQS 佇列中的訊息。

  如果有訊息，剖析 JSON 並檢查任務是否順利完成。如果是，請下載封存。該代碼範例使用 JSON.NET 程式庫 (請參閱 [JSON.NET](http://json.codeplex.com/)) 來剖析 JSON。
+ 透過刪除 Amazon SNS 主題和其建立的 Amazon SQS 佇列來清除。

**Example**  

```
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;

namespace glacier.amazon.com.rproxy.govskope.ca.docsamples
{
  class VaultInventoryJobLowLevelUsingSNSSQS
  {
    static string topicArn;
    static string queueUrl;
    static string queueArn;
    static string vaultName = "*** Provide vault name ***";
    static string fileName  = "*** Provide file name and path where to store inventory ***";
    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("Retrieve Inventory List");
            GetVaultInventory(client);
        }
        Console.WriteLine("Operations successful.");
        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); }
      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 GetVaultInventory(AmazonGlacierClient client)
    {
      // Initiate job.
      InitiateJobRequest initJobRequest = new InitiateJobRequest()
      {
        VaultName = vaultName,
        JobParameters = new JobParameters()
        {
          Type = "inventory-retrieval",
          Description = "This job is to download a vault inventory.",
          SNSTopic = topicArn,
        }
      };
   
      InitiateJobResponse initJobResponse = client.InitiateJob(initJobRequest);
      string jobId = initJobResponse.JobId;

      // Check queue for a message and if job completed successfully, download inventory.
      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 inventory.");

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

# 使用 REST API下載文件庫清查
<a name="retrieving-vault-inventory-rest-api"></a>

**使用 REST API下載文件庫清查**

下載文件庫清查程序包含兩個步驟。

1. 啟動 `inventory-retrieval` 類型的任務。如需詳細資訊，請參閱[啟動任務 (POST 任務)](api-initiate-job-post.md)。

1. 任務完成後，下載庫存資料。如需詳細資訊，請參閱[「取得任務輸出」 (GET 輸出)](api-job-output-get.md)。

# 使用 在 Amazon Glacier 中下載保存庫庫存 AWS Command Line Interface
<a name="retrieving-vault-inventory-cli"></a>

請依照下列步驟，使用 AWS Command Line Interface () 在 Amazon Glacier (Amazon Glacier) 中下載保存庫庫存AWS CLI。

**Topics**
+ [（先決條件） 設定 AWS CLI](#Creating-Vaults-CLI-Setup)
+ [範例：使用 下載保存庫庫存 AWS CLI](#Retrieving-Vault-Inventory-CLI-Implementation)

## （先決條件） 設定 AWS CLI
<a name="Creating-Vaults-CLI-Setup"></a>

1. 下載和設定 AWS CLI。如需相關指示，請參閱《AWS Command Line Interface 使用者指南》**中的下列主題：

    [安裝 AWS Command Line Interface](https://docs.aws.amazon.com/cli/latest/userguide/installing.html) 

   [設定 AWS Command Line Interface](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html)

1. 在命令提示中輸入下列命令來驗證您的 AWS CLI 設定。這些命令不會明確提供登入資料，因此會使用預設描述檔的登入資料。
   + 嘗試使用幫助命令。

     ```
     aws help
     ```
   + 若要取得已設定帳戶上的 Amazon Glacier 保存庫清單，請使用 `list-vaults`命令。將 *123456789012* 取代為您的 AWS 帳戶 ID。

     ```
     aws glacier list-vaults --account-id 123456789012
     ```
   + 若要查看 目前的組態資料 AWS CLI，請使用 `aws configure list`命令。

     ```
     aws configure list
     ```

## 範例：使用 下載保存庫庫存 AWS CLI
<a name="Retrieving-Vault-Inventory-CLI-Implementation"></a>

1. 使用 `initiate-job` 命令啟動清查擷取任務。

   ```
   aws glacier initiate-job --vault-name awsexamplevault --account-id 111122223333 --job-parameters='{"Type": "inventory-retrieval"}'
   ```

    預期的輸出結果：

   ```
   {
       "location": "/111122223333/vaults/awsexamplevault/jobs/*** jobid ***", 
       "jobId": "*** jobid ***"
   }
   ```

1. 使用 `describe-job` 命令檢查先前擷取任務的狀態。

   ```
   aws glacier describe-job --vault-name awsexamplevault --account-id 111122223333 --job-id *** jobid ***
   ```

    預期的輸出結果：

   ```
   {
       "InventoryRetrievalParameters": {
           "Format": "JSON"
       }, 
       "VaultARN": "*** vault arn ***", 
       "Completed": false, 
       "JobId": "*** jobid ***", 
       "Action": "InventoryRetrieval", 
       "CreationDate": "*** job creation date ***", 
       "StatusCode": "InProgress"
   }
   ```

1. 等候 工作完成。

   您必須等到任務輸出準備好供您下載。在 Amazon Glacier 完成任務後至少 24 小時內，任務 ID 不會過期。如果您已在保存庫上設定通知組態，或在啟動任務時指定 Amazon Simple Notification Service (Amazon SNS) 主題，Amazon Glacier 會在完成任務後傳送訊息至主題。

   您可以為文件庫中的特定事件設定通知組態。如需詳細資訊，請參閱[在 Amazon Glacier 中設定保存庫通知](configuring-notifications.md)。Amazon Glacier 會在發生特定事件時傳送訊息至指定的 SNS 主題。

1. 完成時，請使用 `get-job-output` 命令將擷取任務下載至檔案 `output.json`。

   ```
   aws glacier get-job-output --vault-name awsexamplevault --account-id 111122223333 --job-id *** jobid *** output.json
   ```

   這個命令會產生一個包含下列欄位的檔案。

   ```
   {
   "VaultARN":"arn:aws:glacier:region:111122223333:vaults/awsexamplevault",
   "InventoryDate":"*** job completion date ***",
   "ArchiveList":[
   {"ArchiveId":"*** archiveid ***",
   "ArchiveDescription":"*** archive description (if set) ***",
   "CreationDate":"*** archive creation date ***",
   "Size":"*** archive size (in bytes) ***",
   "SHA256TreeHash":"*** archive hash ***"
   }
   {"ArchiveId":
   ...
   ]}
   ```