

 **此页面仅适用于使用文件库和 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 存储类别。

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

# 使用适用于 Java 的 Amazon SDK 分段上传大型档案
<a name="uploading-an-archive-mpu-using-java"></a>

适用于 Java 的 Amazon SDK APIs 提供的[高级和低级](using-aws-sdk.md)都提供了一种上传大型档案的方法（参见[在 Amazon Glacier 中上传档案](uploading-an-archive.md)）。

 
+ 该高级 API 提供了您可以用来上传任何大小的档案的方法。根据您要上传的文件，该方法会在单个操作中上传档案或者使用 Amazon Glacier（Amazon Glacier）中的分段上传支持来分段上传档案。
+ 该低级 API 紧密映射到底层 REST 实施。因此，它提供了一个在单个操作中上传较小档案的方法，以及一组支持较大档案的分段上传的方法。此部分说明了使用低级 API 分段上传大型档案的操作。

有关高级和低级别的更多信息 APIs，请参阅[适用于 Java 的 AWS SDK 与 Amazon Glacier 搭配使用](using-aws-sdk-for-java.md)。

**Topics**
+ [使用的高级别 API 分段上传大型档案 适用于 Java 的 AWS SDK](#uploading-an-archive-in-parts-highlevel-using-java)
+ [使用的低级 API 分段上传大型档案 适用于 Java 的 AWS SDK](#uploading-an-archive-mpu-using-java-lowlevel)

## 使用的高级别 API 分段上传大型档案 适用于 Java 的 AWS SDK
<a name="uploading-an-archive-in-parts-highlevel-using-java"></a>

您可以使用高级 API 的相同方法上传小型或大型档案。根据档案大小，高级 API 方法会决定是在单个操作中上传档案，还是使用 Amazon Glacier 提供的分段上传 API 上传档案。有关更多信息，请参阅 [使用的高级别 API 上传档案 适用于 Java 的 AWS SDK](uploading-an-archive-single-op-using-java.md#uploading-an-archive-single-op-high-level-using-java)。

## 使用的低级 API 分段上传大型档案 适用于 Java 的 AWS SDK
<a name="uploading-an-archive-mpu-using-java-lowlevel"></a>

对于上传的粒度控制，您可以使用低级 API（您可以在其中配置请求以及处理响应）。以下是使用 适用于 Java 的 AWS SDK分段上传大型档案的步骤。

 

1. 创建 `AmazonGlacierClient` 类（客户端）的实例。

   您需要指定要保存档案的 AWS 区域。您使用此客户端执行的所有操作都适用于该 AWS 区域。

1. 通过调用 `initiateMultipartUpload` 方法启动分段上传。

   您需要提供要上传档案的文件库名称、要上传的档案段的大小，也可选择提供相关描述。您可以通过创建 `InitiateMultipartUploadRequest` 类的实例提供此信息。作为响应，Amazon Glacier 会返回上传 ID。

1. 通过调用 `uploadMultipartPart` 方法上传段。

   对于要上传的每一段，您需要提供文件库名称、将在此段中上传的最终组合档案的字节范围、段数据的校验和，以及上传 ID。

1. 通过调用 `completeMultipartUpload` 方法完成分段上传。

   您需要提供上传 ID、整个档案的校验和、档案大小（您上传的所有段的组合大小）和文件库名称。Amazon Glacier 从上传的分段构造档案并返回档案 ID。

### 示例：使用分段上传大型档案 适用于 Java 的 AWS SDK
<a name="upload-archive-mpu-java-example"></a>

以下 Java 代码示例使用将档案上传 适用于 Java 的 AWS SDK 到文件库 (`examplevault`)。有关如何运行此示例的 step-by-step说明，请参阅[使用 Eclipse 运行 Amazon Glacier 的 Java 示例](using-aws-sdk-for-java.md#setting-up-and-testing-sdk-java)。您需要更新待上传文件名称旁所显示的代码。

 

**注意**  
此示例对 1 MB 到 1 GB 的段大小有效。但是，Amazon Glacier 最大支持 4 GB 的段大小。

**Example**  

```
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.glacier.AmazonGlacierClient;
import com.amazonaws.services.glacier.TreeHashGenerator;
import com.amazonaws.services.glacier.model.CompleteMultipartUploadRequest;
import com.amazonaws.services.glacier.model.CompleteMultipartUploadResult;
import com.amazonaws.services.glacier.model.InitiateMultipartUploadRequest;
import com.amazonaws.services.glacier.model.InitiateMultipartUploadResult;
import com.amazonaws.services.glacier.model.UploadMultipartPartRequest;
import com.amazonaws.services.glacier.model.UploadMultipartPartResult;
import com.amazonaws.util.BinaryUtils;

public class ArchiveMPU {

    public static String vaultName = "examplevault";
    // This example works for part sizes up to 1 GB.
    public static String partSize = "1048576"; // 1 MB.
    public static String archiveFilePath = "*** provide archive file path ***";
    public static AmazonGlacierClient client;
    
    public static void main(String[] args) throws IOException {

    	ProfileCredentialsProvider credentials = new ProfileCredentialsProvider();

        client = new AmazonGlacierClient(credentials);
        client.setEndpoint("https://glacier.us-west-2.amazonaws.com/");

        try {
            System.out.println("Uploading an archive.");
            String uploadId = initiateMultipartUpload();
            String checksum = uploadParts(uploadId);
            String archiveId = CompleteMultiPartUpload(uploadId, checksum);
            System.out.println("Completed an archive. ArchiveId: " + archiveId);
            
        } catch (Exception e) {
            System.err.println(e);
        }

    }
    
    private static String initiateMultipartUpload() {
        // Initiate
        InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest()
            .withVaultName(vaultName)
            .withArchiveDescription("my archive " + (new Date()))
            .withPartSize(partSize);            
        
        InitiateMultipartUploadResult result = client.initiateMultipartUpload(request);
        
        System.out.println("ArchiveID: " + result.getUploadId());
        return result.getUploadId();
    }

    private static String uploadParts(String uploadId) throws AmazonServiceException, NoSuchAlgorithmException, AmazonClientException, IOException {

        int filePosition = 0;
        long currentPosition = 0;
        byte[] buffer = new byte[Integer.valueOf(partSize)];
        List<byte[]> binaryChecksums = new LinkedList<byte[]>();
        
        File file = new File(archiveFilePath);
        FileInputStream fileToUpload = new FileInputStream(file);
        String contentRange;
        int read = 0;
        while (currentPosition < file.length())
        {
            read = fileToUpload.read(buffer, filePosition, buffer.length);
            if (read == -1) { break; }
            byte[] bytesRead = Arrays.copyOf(buffer, read);

            contentRange = String.format("bytes %s-%s/*", currentPosition, currentPosition + read - 1);
            String checksum = TreeHashGenerator.calculateTreeHash(new ByteArrayInputStream(bytesRead));
            byte[] binaryChecksum = BinaryUtils.fromHex(checksum);
            binaryChecksums.add(binaryChecksum);
            System.out.println(contentRange);
                        
            //Upload part.
            UploadMultipartPartRequest partRequest = new UploadMultipartPartRequest()
            .withVaultName(vaultName)
            .withBody(new ByteArrayInputStream(bytesRead))
            .withChecksum(checksum)
            .withRange(contentRange)
            .withUploadId(uploadId);               
        
            UploadMultipartPartResult partResult = client.uploadMultipartPart(partRequest);
            System.out.println("Part uploaded, checksum: " + partResult.getChecksum());
            
            currentPosition = currentPosition + read;
        }
        fileToUpload.close();
        String checksum = TreeHashGenerator.calculateTreeHash(binaryChecksums);
        return checksum;
    }

    private static String CompleteMultiPartUpload(String uploadId, String checksum) throws NoSuchAlgorithmException, IOException {
        
        File file = new File(archiveFilePath);

        CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest()
            .withVaultName(vaultName)
            .withUploadId(uploadId)
            .withChecksum(checksum)
            .withArchiveSize(String.valueOf(file.length()));
        
        CompleteMultipartUploadResult compResult = client.completeMultipartUpload(compRequest);
        return compResult.getLocation();
    }
}
```