

 **此页面仅适用于使用文件库和 2012 年原始 REST API 的 Amazon Glacier 服务的现有客户。**

如果您正在寻找归档存储解决方案，建议使用 Amazon S3 中的 Amazon Glacier 存储类别 S3 Glacier Instant Retrieval、S3 Glacier Flexible Retrieval 和 S3 Glacier Deep Archive。要了解有关这些存储选项的更多信息，请参阅 [Amazon Glacier 存储类别](https://aws.amazon.com/s3/storage-classes/glacier/)。

Amazon Glacier（最初基于保管库的独立服务）不再接受新客户。Amazon Glacier 是一项独立的服务 APIs ，拥有自己的服务，可将数据存储在文件库中，不同于亚马逊 S3 和 Amazon S3 Glacier 存储类别。在 Amazon Glacier 中，您现有的数据将确保安全，并且可以无限期地访问。无需进行迁移。对于低成本、长期的存档存储， AWS 建议[使用 Amazon S3 Glacier 存储类别，这些存储类别](https://aws.amazon.com/s3/storage-classes/glacier/)基于S3存储桶 APIs、完全 AWS 区域 可用性、更低的成本和 AWS 服务集成，可提供卓越的客户体验。如果您希望加强功能，可以考虑使用我们的 [AWS 将数据从 Amazon Glacier 文件库传输到 Amazon S3 Glacier 存储类别的解决方案指南](https://aws.amazon.com/solutions/guidance/data-transfer-from-amazon-s3-glacier-vaults-to-amazon-s3/)，迁移到 Amazon S3 Glacier 存储类别。

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 在 Amazon Glacier 中下载文件库清单
<a name="vault-inventory"></a>

您向文件库上传第一个档案后，Amazon Glacier（Amazon Glacier）会自动创建文件库清单，然后大约每天更新一次。Amazon Glacier 创建第一份清单后，通常需要经过半天（最多一天）时间，该清单才可供检索。您可以通过以下流程（该流程分为两个步骤）从 Amazon Glacier 检索文件库清单：

 

1. 使用[启动任务（POST jobs）](api-initiate-job-post.md)操作启动清单检索任务。
**重要**  
数据检索策略可能导致您启动检索任务的请求失败，并发生 `PolicyEnforcedException` 异常。有关数据检索策略的更多信息，请参阅 [Amazon Glacier 数据检索策略](data-retrieval-policy.md)。有关 `PolicyEnforcedException` 异常的更多信息，请参阅[错误响应](api-error-responses.md)。

1. 在任务完成后，使用[获取任务输出（GET output）](api-job-output-get.md)操作下载字节。

例如，检索档案或文件库清单的操作要求您首先启动检索任务。任务请求会异步运行。当您启动检索任务时，Amazon Glacier 会创建任务并在响应中返回任务 ID。Amazon Glacier 完成任务时，您可以获取任务输出（归档字节或文件库清单数据）。

任务必须先完成，然后，您才能获取其输出。要确定任务的状态，您有以下选择：

 
+ **等待任务完成通知** – 您可以指定 Amazon Glacier 在完成任务后可以向其发布通知的 Amazon Simple Notification Service（Amazon SNS）主题。您可以使用以下方法指定 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”**的[响应正文](api-job-output-get.md#api-job-output-get-responses-elements)。

# 在 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 Glacier 的 Amazon SNS 来发布消息。

    

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 SDK 检索文件库清单
<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 Glacier 的 Amazon SNS 来发布消息。

   此外，您还可以通过调用 `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 jobs）](api-initiate-job-post.md)。

1. 任务完成后，下载清单数据。有关更多信息，请参阅[获取任务输出（GET output）](api-job-output-get.md)。

# 使用 Amazon Glacier 下载文件库清单 AWS Command Line Interface
<a name="retrieving-vault-inventory-cli"></a>

按照以下步骤操作，使用 AWS Command Line Interface （AWS CLI）在 Amazon Glacier（Amazon Glacier）中下载文件库清单。

**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 设置。这些命令没有显式提供凭证，因此将使用默认配置文件的凭证。
   + 尝试使用 help 命令。

     ```
     aws help
     ```
   + 要获取已配置账户上 Amazon Glacier 文件库的列表，请使用 `list-vaults` 命令。*123456789012*用您的 AWS 账户 身份证替换。

     ```
     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 完成任务后，任务 ID 至少在 24 小时内都不会过期。如果您在文件库中设置了通知配置，或者在启动任务时指定了 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":
   ...
   ]}
   ```