

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# Amazon S3 で使用する
<a name="examples-s3"></a>

このセクションでは、 AWS SDK for Java 2.xを使用して Amazon S3 を操作するための背景情報を提供します。このセクションは、このガイドの「*コード例*」セクションで説明されている [Amazon S3 Java v2 の例](java_s3_code_examples.md)の情報を補完します

## の S3 クライアント AWS SDK for Java 2.x
<a name="s3-clients"></a>

 AWS SDK for Java 2.x には、さまざまなタイプの S3 クライアントが用意されています。次の表では違いを比較しており、ユースケースに最適なクライアントを決定するのに役立ちます。


**Amazon S3 クライアントのさまざまなタイプ**  

| S3 クライアント | 簡単な説明 | どのようなときに使うか | 制限/欠点 | 
| --- | --- | --- | --- | 
|  **AWS CRT ベースの S3 クライアント** インターフェイス: [S3AsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html) ビルダー: [S3CrtAsyncClientBuilder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/sdk-for-java/latest/developer-guide/examples-s3.html) 「[パフォーマンスの高い S3 クライアントを使用する: AWS CRT ベースの S3 クライアント](crt-based-s3-client.md)」を参照してください。  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/sdk-for-java/latest/developer-guide/examples-s3.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/sdk-for-java/latest/developer-guide/examples-s3.html)  | 
|  **マルチパートが*有効になっている* Java ベースの S3 非同期クライアント** インターフェイス: [S3AsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html) ビルダー: [S3AsyncClientBuilder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClientBuilder.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/sdk-for-java/latest/developer-guide/examples-s3.html) 「[並列転送を使用するように Java ベースの S3 非同期クライアントを設定する](s3-async-client-multipart.md)」を参照してください。  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/sdk-for-java/latest/developer-guide/examples-s3.html)  | CRT AWS ベースの S3 クライアントよりもパフォーマンスが低くなります。 | 
|  **マルチパートが*有効になっていない* Java ベースの S3 非同期クライアント** インターフェイス: [S3AsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html) ビルダー: [S3AsyncClientBuilder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClientBuilder.html) |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/sdk-for-java/latest/developer-guide/examples-s3.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/sdk-for-java/latest/developer-guide/examples-s3.html)  |  パフォーマンスの最適化なし。  | 
|  **Java ベースの S3 同期クライアント** インターフェイス: [S3Client](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html) ビルダー: [S3ClientBuilder](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3ClientBuilder.html) |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/sdk-for-java/latest/developer-guide/examples-s3.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/sdk-for-java/latest/developer-guide/examples-s3.html)  |  パフォーマンスの最適化なし。  | 

**注記**  
バージョン 2.18.x 以降では、 はエンドポイントオーバーライドを含めるときに[仮想ホスト形式のアドレス指定](https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html#virtual-hosted-style-access) AWS SDK for Java 2.x を使用します。これは、バケット名が有効な DNS ラベルである限り適用されます。  
クライアントビルダーの `true` で [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3BaseClientBuilder.html#forcePathStyle(java.lang.Boolean](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3BaseClientBuilder.html#forcePathStyle(java.lang.Boolean) メソッドを呼び出して、クライアントにバケットにパス形式のアドレス指定を使用するように強制します。  
以下の例は、エンドポイントオーバーライドを設定し、パス形式のアドレス指定を使用するサービスクライアントを示しています。  

```
S3Client client = S3Client.builder()
                          .region(Region.US_WEST_2)
                          .endpointOverride(URI.create("https://s3.us-west-2.amazonaws.com"))
                          .forcePathStyle(true)
                          .build();
```

**Topics**
+ [SDK の S3 クライアント](#s3-clients)
+ [S3 にストリームをアップロードする](best-practices-s3-uploads.md)
+ [署名付き URL](examples-s3-presign.md)
+ [クロスリージョンアクセス](s3-cross-region.md)
+ [チェックサムによるデータ整合性保護](s3-checksums.md)
+ [パフォーマンスの高い S3 クライアントを使用する](crt-based-s3-client.md)
+ [並列転送のサポートを設定する](s3-async-client-multipart.md)
+ [ファイルとディレクトリを転送する](transfer-manager.md)
+ [S3 イベント通知](examples-s3-event-notifications.md)

# を使用した Amazon S3 へのストリームのアップロード AWS SDK for Java 2.x
<a name="best-practices-s3-uploads"></a>

ストリームを使用して、[https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html#putObject(software.amazon.awssdk.services.s3.model.PutObjectRequest,software.amazon.awssdk.core.sync.RequestBody)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html#putObject(software.amazon.awssdk.services.s3.model.PutObjectRequest,software.amazon.awssdk.core.sync.RequestBody)) または [https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html#uploadPart(software.amazon.awssdk.services.s3.model.UploadPartRequest,software.amazon.awssdk.core.sync.RequestBody)](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html#uploadPart(software.amazon.awssdk.services.s3.model.UploadPartRequest,software.amazon.awssdk.core.sync.RequestBody)) で S3 にコンテンツをアップロードする場合、同期 API の`RequestBody` ファクトリクラスを使用してストリームを提供します。非同期 API の場合、`AsyncRequestBody` は同等のファクトリクラスです。

## ストリームをアップロードするメソッド
<a name="s3-stream-upload-methods"></a>

同期 API では、次の `RequestBody` のファクトリメソッドを使用してストリームを指定できます。
+ `[fromInputStream](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/sync/RequestBody.html#fromInputStream(java.io.InputStream,long))(InputStream inputStream, long contentLength)`

  `[fromContentProvider](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/sync/RequestBody.html#fromContentProvider(software.amazon.awssdk.http.ContentStreamProvider,long,java.lang.String))(ContentStreamProvider provider, long contentLength, String mimeType)`
  + `ContentStreamProvider` には `fromInputStream(InputStream inputStream)` ファクトリメソッドがあります
+ `[fromContentProvider](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/sync/RequestBody.html#fromContentProvider(software.amazon.awssdk.http.ContentStreamProvider,java.lang.String))(ContentStreamProvider provider, String mimeType)`

非同期 API では、次のファクトリメソッド `AsyncRequestBody` を使用できます。
+ `[fromInputStream](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/AsyncRequestBody.html#fromInputStream(java.io.InputStream,java.lang.Long,java.util.concurrent.ExecutorService))(InputStream inputStream, Long contentLength, ExecutorService executor)` 
+ `[fromInputStream](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/AsyncRequestBody.html#fromInputStream(software.amazon.awssdk.core.async.AsyncRequestBodyFromInputStreamConfiguration))(AsyncRequestBodyFromInputStreamConfiguration configuration)`
  + AsyncRequestBodyFromInputStreamConfiguration.Builder を使用してストリームを提供します。
+ `[fromInputStream](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/AsyncRequestBody.html#fromInputStream(java.util.function.Consumer))(Consumer<AsyncRequestBodyFromInputStreamConfiguration.Builder> configuration)`
+ `[forBlockingInputStream](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/AsyncRequestBody.html#forBlockingInputStream(java.lang.Long))(Long contentLength)`
  + 結果の `[BlockingInputStreamAsyncRequestBody](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/core/async/BlockingInputStreamAsyncRequestBody.html)` には、ストリームの提供に使用できるメソッド `writeInputStream(InputStream inputStream)` が含まれています。

## アップロードの実行
<a name="s3-upload-stream-perform"></a>

### ストリームの長さがわかっている場合
<a name="s3-stream-upload-supply-content-length"></a>

前に示したメソッドの署名からわかるように、ほとんどのメソッドはコンテンツの長さのパラメータを受け入れます。

コンテンツの長さがバイト単位でわかっている場合は、正確な値を指定します。

```
// Always provide the exact content length when it's available.
long contentLength = 1024; // Exact size in bytes.
s3Client.putObject(req -> req
    .bucket("amzn-s3-demo-bucket")
    .key("my-key"),
RequestBody.fromInputStream(inputStream, contentLength));
```

**警告**  
 入力ストリームからアップロードするときに、指定したコンテンツの長さが実際のバイト数と一致しない場合、次のようなことが起こる可能性があります。  
指定した長さが小さすぎる場合にオブジェクトが切り捨てられる
指定した長さが大きすぎる場合、アップロードが失敗するか接続がハングアップする

### ストリームの長さがわからない場合
<a name="s3-stream-upload-unknown-length"></a>

#### 同期 API を使用する
<a name="s3-upload-unknown-sync-client"></a>

`fromContentProvider(ContentStreamProvider provider, String mimeType)` を使用します。

```
public PutObjectResponse syncClient_stream_unknown_size(String bucketName, String key, InputStream inputStream) {

    S3Client s3Client = S3Client.create();

    RequestBody body = RequestBody.fromContentProvider(ContentStreamProvider.fromInputStream(inputStream), "text/plain");
    PutObjectResponse putObjectResponse = s3Client.putObject(b -> b.bucket(BUCKET_NAME).key(KEY_NAME), body);
    return putObjectResponse;
}
```

SDK はストリーム全体をメモリにバッファリングしてコンテンツの長さを計算するため、大きなストリームでメモリの問題が発生する可能性があります。同期クライアントで大きなストリームをアップロードする必要がある場合は、マルチパート API の使用を検討してください。

##### 同期クライアント API とマルチパート API を使用してストリームをアップロードする
<a name="sync-multipart-upload-stream"></a>

```
public static void uploadStreamToS3(String bucketName, String key, InputStream inputStream) {
    // Create S3 client
    S3Client s3Client = S3Client.create();
    try {
        // Step 1: Initiate the multipart upload
        CreateMultipartUploadRequest createMultipartUploadRequest = CreateMultipartUploadRequest.builder()
                .bucket(bucketName)
                .key(key)
                .build();

        CreateMultipartUploadResponse createResponse = s3Client.createMultipartUpload(createMultipartUploadRequest);
        String uploadId = createResponse.uploadId();
        System.out.println("Started multipart upload with ID: " + uploadId);

        // Step 2: Upload parts
        List<CompletedPart> completedParts = new ArrayList<>();
        int partNumber = 1;
        byte[] buffer = new byte[PART_SIZE];
        int bytesRead;

        try {
            while ((bytesRead = readFullyOrToEnd(inputStream, buffer)) > 0) {
                // Create request to upload a part
                UploadPartRequest uploadPartRequest = UploadPartRequest.builder()
                        .bucket(bucketName)
                        .key(key)
                        .uploadId(uploadId)
                        .partNumber(partNumber)
                        .build();

                // If we didn't read a full buffer, create a properly sized byte array
                RequestBody requestBody;
                if (bytesRead < PART_SIZE) {
                    byte[] lastPartBuffer = new byte[bytesRead];
                    System.arraycopy(buffer, 0, lastPartBuffer, 0, bytesRead);
                    requestBody = RequestBody.fromBytes(lastPartBuffer);
                } else {
                    requestBody = RequestBody.fromBytes(buffer);
                }

                // Upload the part and save the response's ETag
                UploadPartResponse uploadPartResponse = s3Client.uploadPart(uploadPartRequest, requestBody);
                CompletedPart part = CompletedPart.builder()
                        .partNumber(partNumber)
                        .eTag(uploadPartResponse.eTag())
                        .build();
                completedParts.add(part);

                System.out.println("Uploaded part " + partNumber + " with size " + bytesRead + " bytes");
                partNumber++;
            }

            // Step 3: Complete the multipart upload
            CompletedMultipartUpload completedMultipartUpload = CompletedMultipartUpload.builder()
                    .parts(completedParts)
                    .build();

            CompleteMultipartUploadRequest completeRequest = CompleteMultipartUploadRequest.builder()
                    .bucket(bucketName)
                    .key(key)
                    .uploadId(uploadId)
                    .multipartUpload(completedMultipartUpload)
                    .build();

            CompleteMultipartUploadResponse completeResponse = s3Client.completeMultipartUpload(completeRequest);
            System.out.println("Multipart upload completed. Object URL: " + completeResponse.location());

        } catch (Exception e) {
            // If an error occurs, abort the multipart upload
            System.err.println("Error during multipart upload: " + e.getMessage());
            AbortMultipartUploadRequest abortRequest = AbortMultipartUploadRequest.builder()
                    .bucket(bucketName)
                    .key(key)
                    .uploadId(uploadId)
                    .build();
            s3Client.abortMultipartUpload(abortRequest);
            System.err.println("Multipart upload aborted");
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                System.err.println("Error closing input stream: " + e.getMessage());
            }
        }
    } finally {
        s3Client.close();
    }
}

/**
 * Reads from the input stream into the buffer, attempting to fill the buffer completely
 * or until the end of the stream is reached.
 *
 * @param inputStream the input stream to read from
 * @param buffer      the buffer to fill
 * @return the number of bytes read, or -1 if the end of the stream is reached before any bytes are read
 * @throws IOException if an I/O error occurs
 */
private static int readFullyOrToEnd(InputStream inputStream, byte[] buffer) throws IOException {
    int totalBytesRead = 0;
    int bytesRead;

    while (totalBytesRead < buffer.length) {
        bytesRead = inputStream.read(buffer, totalBytesRead, buffer.length - totalBytesRead);
        if (bytesRead == -1) {
            break; // End of stream
        }
        totalBytesRead += bytesRead;
    }

    return totalBytesRead > 0 ? totalBytesRead : -1;
}
```

**注記**  
ほとんどのユースケースでは、サイズが不明なストリームに非同期クライアント API を使用することをお勧めします。このアプローチにより並列転送が可能になり、プログラミングインターフェイスがよりシンプルになります。これは、ストリームが大きい場合、SDK はストリームセグメンテーションをマルチパートチャンクに処理するためです。  
マルチパートが有効になっている標準の S3 非同期クライアントと AWS CRT ベースの S3 クライアントの両方がこのアプローチを実装しています。このアプローチの例を次のセクションに示します。

#### 非同期 API を使用する
<a name="s3-stream-upload-unknown-async-client"></a>

`fromInputStream(InputStream inputStream, Long contentLength, ExecutorService executor)` への `contentLength` 引数に `null` を指定できます。

**Example CRT AWS ベースの非同期クライアントの使用:**  

```
public PutObjectResponse crtClient_stream_unknown_size(String bucketName, String key, InputStream inputStream) {

    S3AsyncClient s3AsyncClient = S3AsyncClient.crtCreate();
    ExecutorService executor = Executors.newSingleThreadExecutor();
    AsyncRequestBody body = AsyncRequestBody.fromInputStream(inputStream, null, executor);  // 'null' indicates that the
                                                                                            // content length is unknown.
    CompletableFuture<PutObjectResponse> responseFuture =
            s3AsyncClient.putObject(r -> r.bucket(bucketName).key(key), body)
                    .exceptionally(e -> {
                        if (e != null){
                            logger.error(e.getMessage(), e);
                        }
                        return null;
                    });

    PutObjectResponse response = responseFuture.join(); // Wait for the response.
    executor.shutdown();
    return response;
}
```

**Example マルチパートが有効になっている標準の非同期クライアントを使用します。**  

```
public PutObjectResponse asyncClient_multipart_stream_unknown_size(String bucketName, String key, InputStream inputStream) {

    S3AsyncClient s3AsyncClient = S3AsyncClient.builder().multipartEnabled(true).build();
    ExecutorService executor = Executors.newSingleThreadExecutor();
    AsyncRequestBody body = AsyncRequestBody.fromInputStream(inputStream, null, executor); // 'null' indicates that the
                                                                                           // content length is unknown.
    CompletableFuture<PutObjectResponse> responseFuture =
            s3AsyncClient.putObject(r -> r.bucket(bucketName).key(key), body)
                    .exceptionally(e -> {
                        if (e != null) {
                            logger.error(e.getMessage(), e);
                        }
                        return null;
                    });

    PutObjectResponse response = responseFuture.join(); // Wait for the response.
    executor.shutdown();
    return response;
}
```

# 署名 Amazon S3 付き URLsの使用
<a name="examples-s3-presign"></a>

署名付き URLs は、ユーザーが AWS 認証情報やアクセス許可を持つことなく、プライベート S3 オブジェクトへの一時的なアクセスを提供します。

たとえば、Alice に S3 オブジェクトへのアクセス権限があり、そのオブジェクトへのアクセス権限を一時的に Bob と共有するとします。Alice は、署名付き Get リクエストを生成して Bob との共有し、Bob が Alice の認証情報にアクセスすることなくそのオブジェクトをダウンロードできるようにすることができます。HTTP GET リクエストと HTTP PUT リクエスト用の署名付き URL を生成できます。

## オブジェクトの署名付き URL を生成して、オブジェクトをダウンロードします (GET リクエスト)。
<a name="get-presignedobject"></a>

以下の例は次の 2 つの部分で構成されます。
+ パート 1: Alice はオブジェクトの署名付き URL を生成します。
+ パート 2: Bob は署名済み URL を使用してオブジェクトをダウンロードします。

### パート 1: URL を生成する
<a name="get-presigned-object-part1"></a>

Alice はすでに S3 バケットにオブジェクトを持っています。彼女は次のコードを使用して、Bob が後続の GET リクエストで使用できる URL 文字列を生成します。

#### インポート
<a name="get-presigned-example-imports"></a>

```
import com.example.s3.util.PresignUrlUtils;
import org.slf4j.Logger;
import software.amazon.awssdk.http.HttpExecuteRequest;
import software.amazon.awssdk.http.HttpExecuteResponse;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.SdkHttpMethod;
import software.amazon.awssdk.http.SdkHttpRequest;
import software.amazon.awssdk.http.apache.ApacheHttpClient;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest;
import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest;
import software.amazon.awssdk.utils.IoUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.UUID;
```

```
    /* Create a pre-signed URL to download an object in a subsequent GET request. */
    public String createPresignedGetUrl(String bucketName, String keyName) {
        try (S3Presigner presigner = S3Presigner.create()) {

            GetObjectRequest objectRequest = GetObjectRequest.builder()
                    .bucket(bucketName)
                    .key(keyName)
                    .build();

            GetObjectPresignRequest presignRequest = GetObjectPresignRequest.builder()
                    .signatureDuration(Duration.ofMinutes(10))  // The URL will expire in 10 minutes.
                    .getObjectRequest(objectRequest)
                    .build();

            PresignedGetObjectRequest presignedRequest = presigner.presignGetObject(presignRequest);
            logger.info("Presigned URL: [{}]", presignedRequest.url().toString());
            logger.info("HTTP method: [{}]", presignedRequest.httpRequest().method());

            return presignedRequest.url().toExternalForm();
        }
    }
```

### パート 2: オブジェクトをダウンロードする
<a name="get-presigned-object-part2"></a>

ボブは次の 3 つのコードオプションのいずれかを使用してオブジェクトをダウンロードします。または、ブラウザを使用して GET リクエストを実行することもできます。

#### JDK `HttpURLConnection` を使用する (v1.1 以降)
<a name="get-presigned-example-useHttpUrlConnection"></a>

```
    /* Use the JDK HttpURLConnection (since v1.1) class to do the download. */
    public byte[] useHttpUrlConnectionToGet(String presignedUrlString) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // Capture the response body to a byte array.

        try {
            URL presignedUrl = new URL(presignedUrlString);
            HttpURLConnection connection = (HttpURLConnection) presignedUrl.openConnection();
            connection.setRequestMethod("GET");
            // Download the result of executing the request.
            try (InputStream content = connection.getInputStream()) {
                IoUtils.copy(content, byteArrayOutputStream);
            }
            logger.info("HTTP response code is " + connection.getResponseCode());

        } catch (S3Exception | IOException e) {
            logger.error(e.getMessage(), e);
        }
        return byteArrayOutputStream.toByteArray();
    }
```

#### JDK `HttpClient` を使用する (v11 以降)
<a name="get-presigned-example-useHttpClient"></a>

```
    /* Use the JDK HttpClient (since v11) class to do the download. */
    public byte[] useHttpClientToGet(String presignedUrlString) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // Capture the response body to a byte array.

        HttpRequest.Builder requestBuilder = HttpRequest.newBuilder();
        HttpClient httpClient = HttpClient.newHttpClient();
        try {
            URL presignedUrl = new URL(presignedUrlString);
            HttpResponse<InputStream> response = httpClient.send(requestBuilder
                            .uri(presignedUrl.toURI())
                            .GET()
                            .build(),
                    HttpResponse.BodyHandlers.ofInputStream());

            IoUtils.copy(response.body(), byteArrayOutputStream);

            logger.info("HTTP response code is " + response.statusCode());

        } catch (URISyntaxException | InterruptedException | IOException e) {
            logger.error(e.getMessage(), e);
        }
        return byteArrayOutputStream.toByteArray();
    }
```

#### SDK for Java から `SdkHttpClient` を使用する
<a name="get-presigned-example-useSdkHttpClient"></a>

```
    /* Use the AWS SDK for Java SdkHttpClient class to do the download. */
    public byte[] useSdkHttpClientToGet(String presignedUrlString) {

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); // Capture the response body to a byte array.
        try {
            URL presignedUrl = new URL(presignedUrlString);
            SdkHttpRequest request = SdkHttpRequest.builder()
                    .method(SdkHttpMethod.GET)
                    .uri(presignedUrl.toURI())
                    .build();

            HttpExecuteRequest executeRequest = HttpExecuteRequest.builder()
                    .request(request)
                    .build();

            try (SdkHttpClient sdkHttpClient = ApacheHttpClient.create()) {
                HttpExecuteResponse response = sdkHttpClient.prepareRequest(executeRequest).call();
                response.responseBody().ifPresentOrElse(
                        abortableInputStream -> {
                            try {
                                IoUtils.copy(abortableInputStream, byteArrayOutputStream);
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                        },
                        () -> logger.error("No response body."));

                logger.info("HTTP Response code is {}", response.httpResponse().statusCode());
            }
        } catch (URISyntaxException | IOException e) {
            logger.error(e.getMessage(), e);
        }
        return byteArrayOutputStream.toByteArray();
    }
```

GitHub で[完全な例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/d73001daea05266eaa9e074ccb71b9383832369a/javav2/example_code/s3/src/main/java/com/example/s3/GeneratePresignedGetUrlAndRetrieve.java)と[テスト](https://github.com/awsdocs/aws-doc-sdk-examples/blob/d73001daea05266eaa9e074ccb71b9383832369a/javav2/example_code/s3/src/test/java/com/example/s3/presignurl/GeneratePresignedGetUrlTests.java)をご覧ください。

## アップロード用の署名付き URL を生成して、ファイルをアップロードします (PUT リクエスト)。
<a name="put-presignedobject"></a>

以下の例は次の 2 つの部分で構成されます。
+ パート 1: Alice はオブジェクトをアップロードするために署名付き URL を生成します。
+ パート 2: Bob は署名済み URL を使用してファイルをアップロードします。

### パート 1: URL を生成する
<a name="put-presigned-object-part1"></a>

Alice はすでに S3 バケットを持っています。彼女は次のコードを使用して、Bob が後続の PUT リクエストで使用できる URL 文字列を生成します。

#### インポート
<a name="put-presigned-example-imports"></a>

```
import com.example.s3.util.PresignUrlUtils;
import org.slf4j.Logger;
import software.amazon.awssdk.core.internal.sync.FileContentStreamProvider;
import software.amazon.awssdk.http.HttpExecuteRequest;
import software.amazon.awssdk.http.HttpExecuteResponse;
import software.amazon.awssdk.http.SdkHttpClient;
import software.amazon.awssdk.http.SdkHttpMethod;
import software.amazon.awssdk.http.SdkHttpRequest;
import software.amazon.awssdk.http.apache.ApacheHttpClient;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
import software.amazon.awssdk.services.s3.presigner.model.PresignedPutObjectRequest;
import software.amazon.awssdk.services.s3.presigner.model.PutObjectPresignRequest;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.Map;
import java.util.UUID;
```

```
    /* Create a presigned URL to use in a subsequent PUT request */
    public String createPresignedUrl(String bucketName, String keyName, Map<String, String> metadata) {
        try (S3Presigner presigner = S3Presigner.create()) {

            PutObjectRequest objectRequest = PutObjectRequest.builder()
                    .bucket(bucketName)
                    .key(keyName)
                    .metadata(metadata)
                    .build();

            PutObjectPresignRequest presignRequest = PutObjectPresignRequest.builder()
                    .signatureDuration(Duration.ofMinutes(10))  // The URL expires in 10 minutes.
                    .putObjectRequest(objectRequest)
                    .build();


            PresignedPutObjectRequest presignedRequest = presigner.presignPutObject(presignRequest);
            String myURL = presignedRequest.url().toString();
            logger.info("Presigned URL to upload a file to: [{}]", myURL);
            logger.info("HTTP method: [{}]", presignedRequest.httpRequest().method());

            return presignedRequest.url().toExternalForm();
        }
    }
```

### パート 2: ファイルオブジェクトをアップロードする
<a name="put-presigned-object-part2"></a>

ボブは次の 3 つのコードオプションのいずれかを使用してファイルをアップロードします。

#### JDK `HttpURLConnection` を使用する (v1.1 以降)
<a name="put-presigned-example-useHttpUrlConnection"></a>

```
    /* Use the JDK HttpURLConnection (since v1.1) class to do the upload. */
    public void useHttpUrlConnectionToPut(String presignedUrlString, File fileToPut, Map<String, String> metadata) {
        logger.info("Begin [{}] upload", fileToPut.toString());
        try {
            URL presignedUrl = new URL(presignedUrlString);
            HttpURLConnection connection = (HttpURLConnection) presignedUrl.openConnection();
            connection.setDoOutput(true);
            metadata.forEach((k, v) -> connection.setRequestProperty("x-amz-meta-" + k, v));
            connection.setRequestMethod("PUT");
            OutputStream out = connection.getOutputStream();

            try (RandomAccessFile file = new RandomAccessFile(fileToPut, "r");
                 FileChannel inChannel = file.getChannel()) {
                ByteBuffer buffer = ByteBuffer.allocate(8192); //Buffer size is 8k

                while (inChannel.read(buffer) > 0) {
                    buffer.flip();
                    for (int i = 0; i < buffer.limit(); i++) {
                        out.write(buffer.get());
                    }
                    buffer.clear();
                }
            } catch (IOException e) {
                logger.error(e.getMessage(), e);
            }

            out.close();
            connection.getResponseCode();
            logger.info("HTTP response code is " + connection.getResponseCode());

        } catch (S3Exception | IOException e) {
            logger.error(e.getMessage(), e);
        }
    }
```

#### JDK `HttpClient` を使用する (v11 以降)
<a name="put-presigned-example-useHttpClient"></a>

```
    /* Use the JDK HttpClient (since v11) class to do the upload. */
    public void useHttpClientToPut(String presignedUrlString, File fileToPut, Map<String, String> metadata) {
        logger.info("Begin [{}] upload", fileToPut.toString());

        HttpRequest.Builder requestBuilder = HttpRequest.newBuilder();
        metadata.forEach((k, v) -> requestBuilder.header("x-amz-meta-" + k, v));

        HttpClient httpClient = HttpClient.newHttpClient();
        try {
            final HttpResponse<Void> response = httpClient.send(requestBuilder
                            .uri(new URL(presignedUrlString).toURI())
                            .PUT(HttpRequest.BodyPublishers.ofFile(Path.of(fileToPut.toURI())))
                            .build(),
                    HttpResponse.BodyHandlers.discarding());

            logger.info("HTTP response code is " + response.statusCode());

        } catch (URISyntaxException | InterruptedException | IOException e) {
            logger.error(e.getMessage(), e);
        }
    }
```

#### SDK for Java から `SdkHttpClient` を使用する
<a name="put-presigned-example-useSdkHttpClient"></a>

```
    /* Use the AWS SDK for Java V2 SdkHttpClient class to do the upload. */
    public void useSdkHttpClientToPut(String presignedUrlString, File fileToPut, Map<String, String> metadata) {
        logger.info("Begin [{}] upload", fileToPut.toString());

        try {
            URL presignedUrl = new URL(presignedUrlString);

            SdkHttpRequest.Builder requestBuilder = SdkHttpRequest.builder()
                    .method(SdkHttpMethod.PUT)
                    .uri(presignedUrl.toURI());
            // Add headers
            metadata.forEach((k, v) -> requestBuilder.putHeader("x-amz-meta-" + k, v));
            // Finish building the request.
            SdkHttpRequest request = requestBuilder.build();

            HttpExecuteRequest executeRequest = HttpExecuteRequest.builder()
                    .request(request)
                    .contentStreamProvider(new FileContentStreamProvider(fileToPut.toPath()))
                    .build();

            try (SdkHttpClient sdkHttpClient = ApacheHttpClient.create()) {
                HttpExecuteResponse response = sdkHttpClient.prepareRequest(executeRequest).call();
                logger.info("Response code: {}", response.httpResponse().statusCode());
            }
        } catch (URISyntaxException | IOException e) {
            logger.error(e.getMessage(), e);
        }
    }
```

GitHub で[完全な例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/d73001daea05266eaa9e074ccb71b9383832369a/javav2/example_code/s3/src/main/java/com/example/s3/GeneratePresignedUrlAndPutFileWithMetadata.java)と[テスト](https://github.com/awsdocs/aws-doc-sdk-examples/blob/d73001daea05266eaa9e074ccb71b9383832369a/javav2/example_code/s3/src/test/java/com/example/s3/presignurl/GeneratePresignedPutUrlTests.java)をご覧ください。

# Amazon S3 のクロスリージョンアクセス
<a name="s3-cross-region"></a>

Amazon Simple Storage Service (Amazon S3) バケットで作業をする場合、通常そのバケットの AWS リージョン を知っています。使用するリージョンは、S3 クライアントの作成時に決定されます。

ただし、特定のバケットを操作する必要があったとしても、そのバケットが S3 クライアントに設定されているのと同じリージョンにあるかどうかわからない場合があります。

バケットのリージョンを特定するためにさらに呼び出しを行う代わりに、SDK を使用してさまざまなリージョンの S3 バケットにアクセスできるようにすることができます。

## セットアップ
<a name="s3-cross-region-setup"></a>

クロスリージョンアクセスに関するサポートは、SDK のバージョン `2.20.111` で利用可能になりました。次のスニペットに示すように、Maven ビルドファイルの `s3` 依存関係には、このバージョンまたはそれ以降のバージョンを使用します。

```
<dependency>
  <groupId>software.amazon.awssdk</groupId>
  <artifactId>s3</artifactId>
  <version>2.27.21</version>
</dependency>
```

次に、S3 クライアントを作成するときに、スニペットに示すようにクロスリージョンアクセスを有効にします。デフォルトでは、アクセスは有効になっていません。

```
S3AsyncClient client = S3AsyncClient.builder()
                                    .crossRegionAccessEnabled(true)
                                    .build();
```

## SDK がクロスリージョンアクセスを提供する方法
<a name="s3-cross-region-routing"></a>

`putObject` メソッドを使用する場合など、リクエストで既存のバケットを参照すると、SDK はクライアント用に設定されたリージョンへのリクエストを開始します。

その特定のリージョンにバケットが存在しない場合、エラーレスポンスにはバケットが存在する実際のリージョンが含まれます。その後、SDK は 2 回目のリクエストで正しいリージョンを使用します。

同じバケットへの今後のリクエストを最適化するために、SDK はこのリージョンマッピングをクライアントにキャッシュします。

## 考慮事項
<a name="s3-cross-region-considerations"></a>

クロスリージョンバケットアクセスを有効にする場合、バケットがクライアントの設定済みリージョンにない場合、最初の API コールでレイテンシーが増加する可能性があることに注意してください。ただし、それ以降のコールではキャッシュされたリージョン情報が有効になるため、パフォーマンスが向上します。

クロスリージョンアクセスを有効にする場合、バケットへのアクセスには影響しません。ユーザーは、そのバケットが存在するリージョンに関係なく、バケットにアクセスする権限を持っている必要があります。

# チェックサムによるデータ整合性保護
<a name="s3-checksums"></a>

Amazon Simple Storage Service (Amazon S3) では、オブジェクトをアップロードするときにチェックサムを指定できます。チェックサムを指定すると、そのチェックサムはオブジェクトとともに保存され、オブジェクトのダウンロード時に検証できます。

チェックサムは、ファイルを転送する際のデータの整合性をさらに強化します。チェックサムを使用すると、受信したファイルが元のファイルと一致することを確認することで、データ整合性を検証できます。Amazon S3 でのチェックサムの詳細については、[サポート対象アルゴリズム](https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html#using-additional-checksums)など、「[Amazon Simple Storage Service ユーザーガイド](https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html)」を参照してください。

ニーズに最適なアルゴリズムを柔軟に選択して、SDK にチェックサムを計算させることができます。または、サポートされているアルゴリズムのいずれかを使用して、事前に計算された独自のチェックサム値を指定することもできます。

**注記**  
 AWS SDK for Java 2.xのバージョン 2.30.0 以降、SDK はアップロードの `CRC32` チェックサムを自動的に計算することで、デフォルトの整合性保護を提供します。事前計算されたチェックサム値を指定しない場合、または SDK がチェックサムの計算に使用するアルゴリズムを指定しない場合、SDK はこのチェックサムを計算します。   
SDK には、外部で設定できるデータ整合性保護のグローバル設定も用意されています。詳細については、「[AWS SDK とツールのリファレンスガイド](https://docs.aws.amazon.com/sdkref/latest/guide/feature-dataintegrity.html)」を参照してください。

チェックサムについては、オブジェクトのアップロードとオブジェクトのダウンロードという 2 つのリクエストフェーズで説明します。

## オブジェクトのアップロード
<a name="use-service-S3-checksum-upload"></a>

`putObject` メソッドでオブジェクトをアップロードし、チェックサムアルゴリズムを指定した場合、SDK は指定したアルゴリズムでチェックサムを計算します。 

次のコードスニペットは、`SHA256` チェックサムを含むオブジェクトをアップロードするリクエストを示しています。SDK はリクエストを送信すると、`SHA256` チェックサムを計算してオブジェクトをアップロードします。Amazon S3 は、チェックサムを計算し、SDK によって提供されるチェックサムと比較することで、コンテンツの整合性を検証します。次に、Amazon S3 はオブジェクトと共にチェックサムを保存します。

```
public void putObjectWithChecksum() {
        s3Client.putObject(b -> b
                .bucket(bucketName)
                .key(key)
                .checksumAlgorithm(ChecksumAlgorithm.SHA256),
            RequestBody.fromString("This is a test"));
}
```

リクエストでチェックサムアルゴリズムを指定しない場合、チェックサムの動作は、次の表に示すように、使用する SDK のバージョンによって異なります。

**チェックサムアルゴリズムが指定されていない場合のチェックサムの動作**


| Java SDK バージョン | チェックサムの動作 | 
| --- | --- | 
| 2.30.0 より前 | SDK は、CRC ベースのチェックサムを自動的に計算してリクエストに含めることはありません。 | 
| 2.30.0 以降 | SDK は、`CRC32` アルゴリズムを使用してチェックサムを計算し、リクエストに含めます。Amazon S3 は、独自の `CRC32` チェックサムを計算して転送の整合性を検証し、SDK が提供するチェックサムと比較します。チェックサムが一致した場合、チェックサムはオブジェクトとともに保存されます。 | 

### 事前に計算されたチェックサム値を使用してください。
<a name="use-service-S3-checksum-upload-pre"></a>

リクエストで事前に計算されたチェックサム値を指定すると、SDK による自動計算が無効になり、代わりに提供された値が使用されます。

次の例は、SHA256 チェックサムが事前に計算されたリクエストを示しています。

```
    public void putObjectWithPrecalculatedChecksum(String filePath) {
        String checksum = calculateChecksum(filePath, "SHA-256");

        s3Client.putObject((b -> b
                .bucket(bucketName)
                .key(key)
                .checksumSHA256(checksum)),
            RequestBody.fromFile(Paths.get(filePath)));
    }
```

Amazon S3 が、指定されたアルゴリズムのチェックサム値が正しくないと判断した場合、サービスはエラーレスポンスを返します。

### マルチパートアップロード
<a name="use-service-S3-checksum-upload-multi"></a>

チェックサムはマルチパートアップロードでも使用できます。

 SDK for Java 2.x には、マルチパートアップロードでチェックサムを使用する 2 つのオプションがあります。最初のオプションでは `S3TransferManager` を使用します。

次の転送マネージャーの例では、アップロードに SHA1 アルゴリズムを指定しています。

```
    public void multipartUploadWithChecksumTm(String filePath) {
        S3TransferManager transferManager = S3TransferManager.create();
        UploadFileRequest uploadFileRequest = UploadFileRequest.builder()
            .putObjectRequest(b -> b
                .bucket(bucketName)
                .key(key)
                .checksumAlgorithm(ChecksumAlgorithm.SHA1))
            .source(Paths.get(filePath))
            .build();
        FileUpload fileUpload = transferManager.uploadFile(uploadFileRequest);
        fileUpload.completionFuture().join();
        transferManager.close();
    }
```

アップロードで Transfer Manager を使用する際にチェックサムアルゴリズムを指定しない場合、SDK は `CRC32` アルゴリズムに基づいてチェックサムを自動的に計算します。SDK は、SDK のすべてのバージョンに対してこの計算を実行します。

2 つ目のオプションは [`S3Client`API](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html) (または [`S3AsyncClient`API](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html)) を使用してマルチパートアップロードを実行します。このアプローチでチェックサムを指定する場合は、アップロードの開始時に使用するアルゴリズムを指定する必要があります。また、パートリクエストごとにアルゴリズムを指定し、アップロード後にパートごとに計算されたチェックサムを指定する必要があります。

```
    public void multipartUploadWithChecksumS3Client(String filePath) {
        ChecksumAlgorithm algorithm = ChecksumAlgorithm.CRC32;

        // Initiate the multipart upload.
        CreateMultipartUploadResponse createMultipartUploadResponse = s3Client.createMultipartUpload(b -> b
            .bucket(bucketName)
            .key(key)
            .checksumAlgorithm(algorithm)); // Checksum specified on initiation.
        String uploadId = createMultipartUploadResponse.uploadId();

        // Upload the parts of the file.
        int partNumber = 1;
        List<CompletedPart> completedParts = new ArrayList<>();
        ByteBuffer bb = ByteBuffer.allocate(1024 * 1024 * 5); // 5 MB byte buffer

        try (RandomAccessFile file = new RandomAccessFile(filePath, "r")) {
            long fileSize = file.length();
            long position = 0;
            while (position < fileSize) {
                file.seek(position);
                long read = file.getChannel().read(bb);

                bb.flip(); // Swap position and limit before reading from the buffer.
                UploadPartRequest uploadPartRequest = UploadPartRequest.builder()
                    .bucket(bucketName)
                    .key(key)
                    .uploadId(uploadId)
                    .checksumAlgorithm(algorithm) // Checksum specified on each part.
                    .partNumber(partNumber)
                    .build();

                UploadPartResponse partResponse = s3Client.uploadPart(
                    uploadPartRequest,
                    RequestBody.fromByteBuffer(bb));

                CompletedPart part = CompletedPart.builder()
                    .partNumber(partNumber)
                    .checksumCRC32(partResponse.checksumCRC32()) // Provide the calculated checksum.
                    .eTag(partResponse.eTag())
                    .build();
                completedParts.add(part);

                bb.clear();
                position += read;
                partNumber++;
            }
        } catch (IOException e) {
            System.err.println(e.getMessage());
        }

        // Complete the multipart upload.
        s3Client.completeMultipartUpload(b -> b
            .bucket(bucketName)
            .key(key)
            .uploadId(uploadId)
            .multipartUpload(CompletedMultipartUpload.builder().parts(completedParts).build()));
    }
```

[完全な例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/s3/src/main/java/com/example/s3/PerformMultiPartUpload.java)と[テスト](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/s3/src/test/java/com/example/s3/PerformMultiPartUploadTests.java)のコードは、GitHub のコードサンプルリポジトリにあります。

## オブジェクトのダウンロード
<a name="use-service-S3-checksum-download"></a>

[getObject](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html#getObject(software.amazon.awssdk.services.s3.model.GetObjectRequest)) メソッドを使用してオブジェクトをダウンロードすると、SDK は `GetObjectRequest` のビルダーの `checksumMode` のメソッドが `ChecksumMode.ENABLED` に設定されている場合にチェックサムを自動的に検証します。

次のスニペット内のリクエストは、チェックサムを計算して値を比較することでレスポンス内のチェックサムを検証するよう SDK に指示します。

```
    public GetObjectResponse getObjectWithChecksum() {
        return s3Client.getObject(b -> b
                        .bucket(bucketName)
                        .key(key)
                        .checksumMode(ChecksumMode.ENABLED))
                .response();
    }
```

**注記**  
オブジェクトがチェックサム付きでアップロードされなかった場合、検証は行われません。

## その他のチェックサム計算オプション
<a name="S3-checsum-calculation-options"></a>

**注記**  
送信データの整合性を検証し、送信エラーを検出するために、チェックサム計算オプションについては SDK のデフォルト設定を維持することをお勧めします。デフォルトでは、SDK は `PutObject` や `GetObject` を含む多くの S3 オペレーションに対して、この重要なチェックを追加します。

ただし、Amazon S3 の使用で最小限のチェックサム検証しか必要としない場合は、デフォルトの設定を変更することで、多くのチェックを無効にできます。

### 必須でない場合に自動チェックサム計算を無効にする
<a name="S3-minimize-checksum-calc-global"></a>

SDK がサポートするオペレーション（例：`PutObject` や `GetObject`）に対して、自動チェックサム計算を無効にできます。ただし、一部の S3 オペレーションではチェックサムの計算が必須であり、これらのオペレーションではチェックサム計算を無効にすることはできません。

SDK は、リクエストのペイロード用チェックサムの計算と、レスポンスのペイロード用チェックサムの計算をそれぞれ個別の設定として提供します。

次のリストでは、さまざまな範囲でのチェックサム計算を最小限に抑えるために使用できる設定について説明します。
+ **すべてのアプリケーションスコープ** — 環境変数または共有 AWS `config` および `credentials` ファイル内のプロファイルの設定を変更することで、すべてのアプリケーションがこれらの設定を使用できます。これらの設定は、アプリケーションまたはサービスクライアントスコープで上書きされない限り、すべての AWS SDK アプリケーションのすべてのサービスクライアントに影響します。
  + プロファイルで設定を追加します。

    ```
    [default]
    request_checksum_calculation = WHEN_REQUIRED
    response_checksum_validation = WHEN_REQUIRED
    ```
  + 環境変数を追加します。

    ```
    AWS_REQUEST_CHECKSUM_CALCULATION=WHEN_REQUIRED
    AWS_RESPONSE_CHECKSUM_VALIDATION=WHEN_REQUIRED
    ```
+ **現在のアプリケーション範囲** — Java システムプロパティ `aws.requestChecksumCalculation` を `WHEN_REQUIRED` に設定して、チェックサムの計算を制限できます。レスポンスの対応するシステムプロパティは `aws.responseChecksumValidation` です。

  これらの設定は、サービスクライアントの作成中に上書きされない限り、アプリケーション内のすべての SDK サービスクライアントに影響します。

  アプリケーションの開始時にシステムプロパティを設定します。

  ```
  import software.amazon.awssdk.core.SdkSystemSetting;
  import software.amazon.awssdk.core.checksums.RequestChecksumCalculation;
  import software.amazon.awssdk.core.checksums.ResponseChecksumValidation;
  import software.amazon.awssdk.services.s3.S3Client;
  
  class DemoClass {
      public static void main(String[] args) {
  
          System.setProperty(SdkSystemSetting.AWS_REQUEST_CHECKSUM_CALCULATION.property(), // Resolves to "aws.requestChecksumCalculation".
                  "WHEN_REQUIRED");
          System.setProperty(SdkSystemSetting.AWS_RESPONSE_CHECKSUM_VALIDATION.property(), // Resolves to "aws.responseChecksumValidation".
                  "WHEN_REQUIRED");
  
          S3Client s3Client = S3Client.builder().build();
  
          // Use s3Client.
      }
  }
  ```
+ **単一の S3 サービスクライアント範囲** — ビルダーメソッドを使用して、最小量のチェックサムを計算するように単一の S3 サービスクライアントを設定できます。

  ```
  import software.amazon.awssdk.core.checksums.RequestChecksumCalculation;
  import software.amazon.awssdk.services.s3.S3Client;
  
  public class RequiredChecksums {
      public static void main(String[] args) {
          S3Client s3 = S3Client.builder()
                  .requestChecksumCalculation(RequestChecksumCalculation.WHEN_REQUIRED)
                  .responseChecksumValidation(ResponseChecksumValidation.WHEN_REQUIRED)
                  .build();
  
          // Use s3Client. 
      }
  // ...
  }
  ```

### `LegacyMd5Plugin` を使用した MD5 との互換性の簡素化
<a name="S3-checksum-legacy-md5"></a>

バージョン 2.30.0 での CRC32 チェックサム動作のリリースに加えて、SDK は必要なオペレーションの MD5 チェックサムの計算を停止しました。

S3 オペレーションにレガシーの MD5 チェックサム動作が必要な場合は、 SDK のバージョン 2.31.32 でリリースされた `LegacyMd5Plugin` を使用できます。

`LegacyMd5Plugin` は、レガシー MD5 チェックサムの動作に依存するアプリケーションとの互換性を維持する必要がある場合、特に S3A ファイルシステムコネクタで使用されるようなサードパーティの S3 互換ストレージプロバイダーを使用する場合に特に便利です (Apache Spark、Iceberg) 。

`LegacyMd5Plugin` を使用するには、S3 クライアントビルダーに追加します。

```
// For synchronous S3 client.
S3Client s3Client = S3Client.builder()
                           .addPlugin(LegacyMd5Plugin.create())
                           .build();

// For asynchronous S3 client.
S3AsyncClient asyncClient = S3AsyncClient.builder()
                                       .addPlugin(LegacyMd5Plugin.create())
                                       .build();
```

チェックサムが必要なオペレーションに MD5 チェックサムを追加し、チェックサムをサポートしているが必須ではないオペレーションに対しては SDK デフォルトチェックサムの追加をスキップする場合は、`ClientBuilder` オプション `requestChecksumCalculation` および `responseChecksumValidation` を `WHEN_REQUIRED` として有効にできます。これにより、SDK のデフォルトのチェックサムのみが、チェックサムを必要とするオペレーションに追加されます。

```
// Use the `LegacyMd5Plugin` with `requestChecksumCalculation` and `responseChecksumValidation` set to WHEN_REQUIRED.
S3AsyncClient asyncClient = S3AsyncClient.builder()
                                       .addPlugin(LegacyMd5Plugin.create())
                                       .requestChecksumCalculation(RequestChecksumCalculation.WHEN_REQUIRED)
                                       .responseChecksumValidation(ResponseChecksumValidation.WHEN_REQUIRED)
                                       .build();
```

この設定は、新しいチェックサムアルゴリズムを完全にはサポートしていないものの、特定のオペレーションに MD5 チェックサムが必要なサードパーティーの S3 互換ストレージシステムを使用する場合に特に便利です。

# パフォーマンスの高い S3 クライアントを使用する: AWS CRT ベースの S3 クライアント
<a name="crt-based-s3-client"></a>

Common Runtime ( AWS CRT) 上に構築された CRT ベースの S3 クライアントは、代替の S3 非同期クライアントです。 [AWS](https://docs.aws.amazon.com/sdkref/latest/guide/common-runtime.html)Amazon S3 の[マルチパートアップロード API](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html) と[バイト範囲フェッチ](https://docs.aws.amazon.com/AmazonS3/latest/userguide/optimizing-performance-guidelines.html#optimizing-performance-guidelines-get-range)を自動的に使用することで、Amazon Simple Storage Service (Amazon S3) との間でオブジェクトを転送し、パフォーマンスと信頼性を向上させます。

 AWS CRT ベースの S3 クライアントは、ネットワーク障害が発生した場合の転送の信頼性を向上させます。ファイル転送を最初からやり直すことなく、失敗した個別の部分を再試行することで、信頼性を改善しています。

さらに、CRT AWS ベースの S3 クライアントは、強化された接続プーリングとドメインネームシステム (DNS) ロードバランシングを提供し、スループットも向上します。

SDK の標準 S3 非同期クライアントの代わりに AWS CRT ベースの S3 クライアントを使用し、その改善されたスループットをすぐに活用できます。

**重要**  
 AWS CRT ベースの S3 クライアントは現在、クライアントレベルまたはリクエストレベルで [SDK メトリクス収集](metrics.md)をサポートしていません。

**AWS SDK の CRT ベースのコンポーネント**

このトピックで説明されている AWS CRT ベースの* S3* クライアントと CRT AWS ベースの *HTTP* クライアントは SDK の異なるコンポーネントです。

**AWS CRT ベースの S3 クライアント**は [S3AsyncClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html) インターフェイスの実装であり、Amazon S3 サービスを利用するために使用されます。これは `S3AsyncClient` インターフェイスの Java ベースの実装に代わるもので、いくつかの利点があります。

[AWS CRT ベースの HTTP クライアント](http-configuration-crt.md)は、[SDKASyncHttpClient](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/http/async/SdkAsyncHttpClient.html) インターフェースを実装したもので、一般的な HTTP 通信に使用されます。これは `SdkAsyncHttpClient` インターフェースの Netty 実装に代わるもので、いくつかの利点があります。

どちらのコンポーネントも [AWS Common Runtime](https://docs.aws.amazon.com/sdkref/latest/guide/common-runtime.html) のライブラリを使用しますが、 AWS CRT ベースの S3 クライアントは [aws-c-s3 ライブラリ](https://github.com/awslabs/aws-c-s3)を使用し、[S3 マルチパートアップロード API ](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html)機能をサポートしています。 AWS CRT ベースの HTTP クライアントは汎用であるため、S3 マルチパートアップロード API 機能はサポートされていません。

## CRT AWS ベースの S3 クライアントを使用するための依存関係を追加する
<a name="crt-based-s3-client-depend"></a>

 AWS CRT ベースの S3 クライアントを使用するには、Maven プロジェクトファイルに次の 2 つの依存関係を追加します。この例は、使用する最小バージョンを示しています。Maven central リポジトリで [s3](https://central.sonatype.com/artifact/software.amazon.awssdk/s3) と [aws-crt](https://central.sonatype.com/artifact/software.amazon.awssdk.crt/aws-crt) のアーティファクトの最新バージョンを検索します。

```
<dependency>
  <groupId>software.amazon.awssdk</groupId>
  <artifactId>s3</artifactId>
  <version>2.27.21</version>
</dependency>
<dependency>
  <groupId>software.amazon.awssdk.crt</groupId>
  <artifactId>aws-crt</artifactId>
  <version>0.30.11</version>
</dependency>
```

## CRT AWS ベースの S3 クライアントのインスタンスを作成する
<a name="crt-based-s3-client-create"></a>

 次のコードスニペットに示すように、デフォルト設定で AWS CRT ベースの S3 クライアントのインスタンスを作成します。

```
S3AsyncClient s3AsyncClient = S3AsyncClient.crtCreate();
```

クライアントを設定するには、CRT AWS クライアントビルダーを使用します。ビルダーメソッドを変更することで、標準の S3 非同期クライアントから AWS CRT ベースのクライアントに切り替えることができます。

```
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3AsyncClient;


S3AsyncClient s3AsyncClient = 
        S3AsyncClient.crtBuilder()
                     .credentialsProvider(DefaultCredentialsProvider.create())
                     .region(Region.US_WEST_2)
                     .targetThroughputInGbps(20.0)
                     .minimumPartSizeInBytes(8 * 1025 * 1024L)
                     .build();
```

**注記**  
スタンダードビルダーの設定の一部は、現在 AWS CRT クライアントビルダーではサポートされていない場合があります。スタンダードビルダーを取得するには、`S3AsyncClient#builder()` を呼び出します。

## CRT AWS ベースの S3 クライアントを使用する
<a name="crt-based-s3-client-use"></a>

 AWS CRT ベースの S3 クライアントを使用して Amazon S3 API オペレーションを呼び出します。次の例は、 AWS SDK for Javaを介して実行できる [PutObject](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html#putObject(java.util.function.Consumer,software.amazon.awssdk.core.async.AsyncRequestBody)) オペレーションと [GetObject](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClient.html#getObject(java.util.function.Consumer,software.amazon.awssdk.core.async.AsyncResponseTransformer)) オペレーションを示しています。

```
import software.amazon.awssdk.core.async.AsyncRequestBody;
import software.amazon.awssdk.core.async.AsyncResponseTransformer;
import software.amazon.awssdk.services.s3.S3AsyncClient;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
import software.amazon.awssdk.services.s3.model.PutObjectResponse;


S3AsyncClient s3Client = S3AsyncClient.crtCreate();

// Upload a local file to Amazon S3.
PutObjectResponse putObjectResponse = 
      s3Client.putObject(req -> req.bucket(<BUCKET_NAME>)
                                   .key(<KEY_NAME>),
                        AsyncRequestBody.fromFile(Paths.get(<FILE_NAME>)))
              .join();

// Download an object from Amazon S3 to a local file.
GetObjectResponse getObjectResponse = 
      s3Client.getObject(req -> req.bucket(<BUCKET_NAME>)
                                   .key(<KEY_NAME>),
                        AsyncResponseTransformer.toFile(Paths.get(<FILE_NAME>)))
              .join();
```

## サイズが不明なストリームのアップロード
<a name="crt-stream-unknown-size"></a>

 AWS AWS CRT ベースの S3 クライアントの主な利点の 1 つは、サイズが不明な入力ストリームを効率的に処理できることです。これは、合計サイズを事前に判断できないソースからデータをアップロードする必要がある場合に特に便利です。

```
public PutObjectResponse crtClient_stream_unknown_size(String bucketName, String key, InputStream inputStream) {

    S3AsyncClient s3AsyncClient = S3AsyncClient.crtCreate();
    ExecutorService executor = Executors.newSingleThreadExecutor();
    AsyncRequestBody body = AsyncRequestBody.fromInputStream(inputStream, null, executor);  // 'null' indicates that the
                                                                                            // content length is unknown.
    CompletableFuture<PutObjectResponse> responseFuture =
            s3AsyncClient.putObject(r -> r.bucket(bucketName).key(key), body)
                    .exceptionally(e -> {
                        if (e != null){
                            logger.error(e.getMessage(), e);
                        }
                        return null;
                    });

    PutObjectResponse response = responseFuture.join(); // Wait for the response.
    executor.shutdown();
    return response;
}
```

この機能は、コンテンツの長さの指定が正しくないとオブジェクトの切り捨てやアップロードの失敗につながる可能性がある、従来のアップロードの一般的な問題を回避するのに役立ちます。

## 設定の制限
<a name="crt-based-s3-client-limitations"></a>

 AWS CRT ベースの S3 クライアントと Java ベースの S3 非同期クライアントは[同等の機能を提供し](examples-s3.md#s3-clients)、CRT AWS ベースの S3 クライアントはパフォーマンスエッジを提供します。ただし、 AWS CRT ベースの S3 クライアントには、Java ベースの S3 非同期クライアントの設定がありません。設定は次のとおりです。
+ *クライアントレベルの設定:* API コール試行のタイムアウト、圧縮実行インターセプター、メトリクスパブリッシャー、カスタム実行属性、カスタム詳細オプション、カスタムスケジュールのエグゼキュータサービス、カスタムヘッダー
+ *リクエストレベルの設定:* カスタム署名者、API コール試行タイムアウト

設定の違いの完全なリストについては、 API リファレンスを参照してください。


| Java ベースの S3 非同期クライアント | AWS CRT ベースの S3 クライアント | 
| --- | --- | 
| クライアントレベルの設定[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/sdk-for-java/latest/developer-guide/crt-based-s3-client.html)リクエストレベルの設定[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/sdk-for-java/latest/developer-guide/crt-based-s3-client.html) | クライアントレベルの設定[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/sdk-for-java/latest/developer-guide/crt-based-s3-client.html)リクエストレベルの設定[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/sdk-for-java/latest/developer-guide/crt-based-s3-client.html) | 

# 並列転送を使用するように Java ベースの S3 非同期クライアントを設定する
<a name="s3-async-client-multipart"></a>

バージョン 2.27.5 以降、標準の Java ベースの S3 非同期クライアントは、自動並列転送 (マルチパートアップロードおよびダウンロード) をサポートしています。Java ベースの S3 非同期クライアントを作成するときに、並列転送のサポートを設定します。

このセクションでは、並列転送を有効にする方法と設定をカスタマイズする方法について説明します。

## `S3AsyncClient` のインスタンスの作成
<a name="s3-async-client-multipart-create"></a>

[ビルダー](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3AsyncClientBuilder.html)で `multipart*` メソッドを呼び出さずに `S3AsyncClient` インスタンスを作成する場合、並列転送は有効になりません。次の各ステートメントは、マルチパートアップロードとダウンロードのサポートなしで Java ベースの S3 非同期クライアントを作成します。

### マルチパートサポート*なしで*作成する
<a name="s3-async-client-mp-off"></a>

**Example**  

```
import software.amazon.awssdk.auth.credentials.ProcessCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3AsyncClient;


S3AsyncClient s3Client = S3AsyncClient.create();

S3AsyncClient s3Client2 = S3AsyncClient.builder().build();

S3AsyncClient s3Client3 = S3AsyncClient.builder()
        .credentialsProvider(ProcessCredentialsProvider.builder().build())
        .region(Region.EU_NORTH_1)
        .build();
```

### マルチパートサポート*付きで*作成する
<a name="s3-async-client-mp-on"></a>

デフォルト設定で並列転送を有効にするには、ビルダーで `multipartEnabled` を呼び出し、次の例に示すように `true` を渡します。

**Example**  

```
S3AsyncClient s3AsyncClient2 = S3AsyncClient.builder()
        .multipartEnabled(true)
        .build();
```

デフォルト値は、 `thresholdInBytes` および `minimumPartSizeInBytes` 設定では 8 MiB です。

マルチパート設定をカスタマイズすると、次に示すように並列転送が自動的に有効になります。

**Example**  

```
import software.amazon.awssdk.services.s3.S3AsyncClient;
import static software.amazon.awssdk.transfer.s3.SizeConstant.MB;


S3AsyncClient s3AsyncClient2 = S3AsyncClient.builder()
        .multipartConfiguration(b -> b
                .thresholdInBytes(16 * MB)
                .minimumPartSizeInBytes(10 * MB))
        .build();
```

## サイズが不明なストリームのアップロード
<a name="java-async-client-stream-unknown-size"></a>

マルチパートが有効になっている Java ベースの S3 非同期クライアントは、合計サイズが事前にわからない入力ストリームを効率的に処理できます。

```
public PutObjectResponse asyncClient_multipart_stream_unknown_size(String bucketName, String key, InputStream inputStream) {

    S3AsyncClient s3AsyncClient = S3AsyncClient.builder().multipartEnabled(true).build();
    ExecutorService executor = Executors.newSingleThreadExecutor();
    AsyncRequestBody body = AsyncRequestBody.fromInputStream(inputStream, null, executor); // 'null' indicates that the
                                                                                           // content length is unknown.
    CompletableFuture<PutObjectResponse> responseFuture =
            s3AsyncClient.putObject(r -> r.bucket(bucketName).key(key), body)
                    .exceptionally(e -> {
                        if (e != null) {
                            logger.error(e.getMessage(), e);
                        }
                        return null;
                    });

    PutObjectResponse response = responseFuture.join(); // Wait for the response.
    executor.shutdown();
    return response;
}
```

このアプローチにより、切り捨てられたオブジェクトやアップロードの失敗など、コンテンツの長さを手動で指定した場合に発生する可能性のある問題を回避できます。

# Amazon S3 Transfer Manager を使用してファイルとディレクトリを転送する
<a name="transfer-manager"></a>

Amazon S3 転送マネージャは、 AWS SDK for Java 2.x用のオープンソースの高レベルファイル転送ユーティリティです。Amazon Simple Storage Service (Amazon S3) との間でファイルやディレクトリを転送するために使用します。

[AWS CRT ベースの S3 クライアント](crt-based-s3-client.md)または[マルチパートが有効になっている標準の Java ベースの S3 非同期クライアント](s3-async-client-multipart.md)上に構築すると、S3 Transfer Manager では[マルチパートアップロード API](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html) や[バイト範囲フェッチ](https://docs.aws.amazon.com/AmazonS3/latest/userguide/optimizing-performance-guidelines.html#optimizing-performance-guidelines-get-range)などのパフォーマンスの向上を活用できます。

S3 Transfer Manager では、転送の進行状況をリアルタイムでモニタリングし、転送を一時停止して後で実行することもできます。

## はじめに
<a name="transfer-manager-prerequisites"></a>

### ビルドファイルに依存関係を追加する
<a name="transfer-manager-add-dependency"></a>

S3 Transfer Manager で強化されたマルチパートパフォーマンスを利用するには、必要な依存関係を使用してビルドファイルを設定します。

------
#### [ Use the AWS CRT-based S3 client ]

```
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>bom</artifactId>
            <version>2.27.211</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>s3-transfer-manager</artifactId>
    </dependency>
    <dependency>
        <groupId>software.amazon.awssdk.crt</groupId>
        <artifactId>aws-crt</artifactId>
        <version>0.29.1432</version>
    </dependency>
</dependencies>
```

1 [最新バージョン](https://central.sonatype.com/artifact/software.amazon.awssdk/bom)。 2 [最新バージョン](https://central.sonatype.com/artifact/software.amazon.awssdk.crt/aws-crt)。

------
#### [ Use the Java-based S3 async client ]

```
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>bom</artifactId>
            <version>2.27.211</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>s3-transfer-manager</artifactId>
    </dependency>
</dependencies>
```

1 [最新バージョン](https://central.sonatype.com/artifact/software.amazon.awssdk/bom)。

------

### S3 Transfer Manager のインスタンスを作成する
<a name="transfer-manager-create"></a>

並列転送を有効にするには、CRT AWS ベースの S3 クライアントまたはマルチパートが有効になっている Java ベースの S3 非同期クライアントを渡す必要があります。次の例は、S3 Transfer Manager をカスタム設定する方法を示しています。

------
#### [ Use the AWS CRT-based S3 client ]

```
        S3AsyncClient s3AsyncClient = S3AsyncClient.crtBuilder()
                .credentialsProvider(DefaultCredentialsProvider.create())
                .region(Region.US_EAST_1)
                .targetThroughputInGbps(20.0)
                .minimumPartSizeInBytes(8 * MB)
                .build();

        S3TransferManager transferManager = S3TransferManager.builder()
                .s3Client(s3AsyncClient)
                .build();
```

------
#### [ Use the Java-based S3 async client ]

`aws-crt` 依存関係がビルドファイルに含まれていない場合、S3 Transfer Manager は SDK for Java 2.x で使用されている標準の Java ベースの S3 非同期クライアント上に構築されます。

**S3 クライアントのカスタム設定 - マルチパートを有効にする必要があります**

```
        S3AsyncClient s3AsyncClient = S3AsyncClient.builder()
                .multipartEnabled(true)
                .credentialsProvider(DefaultCredentialsProvider.create())
                .region(Region.US_EAST_1)
                .build();

        S3TransferManager transferManager = S3TransferManager.builder()
                .s3Client(s3AsyncClient)
                .build();
```

**S3 クライアントの設定なし - マルチパートサポートが自動的に有効になります**

```
S3TransferManager transferManager = S3TransferManager.create();
```

------

## S3 バケットにファイルをアップロードする
<a name="transfer-manager-upload"></a>

次の例は、ファイルのアップロード例と、アップロードの進行状況をログ記録する [LoggingTransferListener](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/progress/LoggingTransferListener.html) をオプションで使用したものです。

S3 Transfer Manager を使用して Amazon S3 にファイルをアップロードするには、`S3TransferManager`の [uploadFile](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/S3TransferManager.html#uploadFile(software.amazon.awssdk.transfer.s3.model.UploadFileRequest)) メソッドに[https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/UploadFileRequest.html](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/UploadFileRequest.html) オブジェクトを渡します。

`uploadFile` メソッドから返される [FileUpload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/FileUpload.html) オブジェクトはアップロードプロセスを表します。リクエストが完了すると、[CompletedFileUpload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CompletedFileUpload.html) オブジェクトはアップロードに関する情報を含めます。

```
    public void trackUploadFile(S3TransferManager transferManager, String bucketName,
                             String key, URI filePathURI) {
        UploadFileRequest uploadFileRequest = UploadFileRequest.builder()
                .putObjectRequest(b -> b.bucket(bucketName).key(key))
                .addTransferListener(LoggingTransferListener.create())  // Add listener.
                .source(Paths.get(filePathURI))
                .build();

        FileUpload fileUpload = transferManager.uploadFile(uploadFileRequest);

        fileUpload.completionFuture().join();
        /*
            The SDK provides a LoggingTransferListener implementation of the TransferListener interface.
            You can also implement the interface to provide your own logic.

            Configure log4J2 with settings such as the following.
                <Configuration status="WARN">
                    <Appenders>
                        <Console name="AlignedConsoleAppender" target="SYSTEM_OUT">
                            <PatternLayout pattern="%m%n"/>
                        </Console>
                    </Appenders>

                    <Loggers>
                        <logger name="software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener" level="INFO" additivity="false">
                            <AppenderRef ref="AlignedConsoleAppender"/>
                        </logger>
                    </Loggers>
                </Configuration>

            Log4J2 logs the progress. The following is example output for a 21.3 MB file upload.
                Transfer initiated...
                |                    | 0.0%
                |====                | 21.1%
                |============        | 60.5%
                |====================| 100.0%
                Transfer complete!
        */
    }
```

### インポート
<a name="transfer-manager-upload-imports"></a>

```
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.transfer.s3.S3TransferManager;
import software.amazon.awssdk.transfer.s3.model.CompletedFileUpload;
import software.amazon.awssdk.transfer.s3.model.FileUpload;
import software.amazon.awssdk.transfer.s3.model.UploadFileRequest;
import software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Paths;
import java.util.UUID;
```

## S3 バケットからのファイルのダウンロード
<a name="transfer-manager-download"></a>

次の例には、ダウンロードの例と、ダウンロードの進行状況をログ記録する [LoggingTransferListener](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/progress/LoggingTransferListener.html) をオプションで使用する方法も示されています。

S3 Transfer Manager を使用して S3 バケットからオブジェクトをダウンロードするには、[DownloadFileRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/DownloadFileRequest.html) オブジェクトを構築してそれを [downloadFile](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/S3TransferManager.html#downloadFile(software.amazon.awssdk.transfer.s3.model.DownloadFileRequest)) メソッドに渡します。

`S3TransferManager` の `downloadFile` メソッドによって返される [FileDownload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/FileDownload.html) オブジェクトは、ファイル転送を表します。ダウンロードが完了すると、[CompletedFileDownload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CompletedFileDownload.html) はダウンロードに関する情報へのアクセスを含めます。

```
    public void trackDownloadFile(S3TransferManager transferManager, String bucketName,
                             String key, String downloadedFileWithPath) {
        DownloadFileRequest downloadFileRequest = DownloadFileRequest.builder()
                .getObjectRequest(b -> b.bucket(bucketName).key(key))
                .addTransferListener(LoggingTransferListener.create())  // Add listener.
                .destination(Paths.get(downloadedFileWithPath))
                .build();

        FileDownload downloadFile = transferManager.downloadFile(downloadFileRequest);

        CompletedFileDownload downloadResult = downloadFile.completionFuture().join();
        /*
            The SDK provides a LoggingTransferListener implementation of the TransferListener interface.
            You can also implement the interface to provide your own logic.

            Configure log4J2 with settings such as the following.
                <Configuration status="WARN">
                    <Appenders>
                        <Console name="AlignedConsoleAppender" target="SYSTEM_OUT">
                            <PatternLayout pattern="%m%n"/>
                        </Console>
                    </Appenders>

                    <Loggers>
                        <logger name="software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener" level="INFO" additivity="false">
                            <AppenderRef ref="AlignedConsoleAppender"/>
                        </logger>
                    </Loggers>
                </Configuration>

            Log4J2 logs the progress. The following is example output for a 21.3 MB file download.
                Transfer initiated...
                |=======             | 39.4%
                |===============     | 78.8%
                |====================| 100.0%
                Transfer complete!
        */
    }
```

### インポート
<a name="transfer-manager-download-import"></a>

```
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.core.exception.SdkException;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.transfer.s3.S3TransferManager;
import software.amazon.awssdk.transfer.s3.model.CompletedFileDownload;
import software.amazon.awssdk.transfer.s3.model.DownloadFileRequest;
import software.amazon.awssdk.transfer.s3.model.FileDownload;
import software.amazon.awssdk.transfer.s3.progress.LoggingTransferListener;

import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;
```

## Amazon S3 バケットを他のバケットにコピーする
<a name="transfer-manager-copy"></a>

次の例は、S3 Transfer Manager を使用してオブジェクトをコピーする方法を示しています。

S3 バケットから別のバケットへのオブジェクトのコピーを開始するには、基本 [CopyObjectRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/model/CopyObjectRequest.html) インスタンスを作成します。

次に、その基本 `CopyObjectRequest` を S3 Transfer Manager が使用できる [CopyRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CopyRequest.html) にラップします。

`S3TransferManager` の `copy` メソッドによって返される `Copy` オブジェクトはコピープロセスを表します。コピープロセスが完了すると、[CompletedCopy](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CompletedCopy.html) オブジェクトはレスポンスに関する詳細を含めます。

```
    public String copyObject(S3TransferManager transferManager, String bucketName,
            String key, String destinationBucket, String destinationKey) {
        CopyObjectRequest copyObjectRequest = CopyObjectRequest.builder()
                .sourceBucket(bucketName)
                .sourceKey(key)
                .destinationBucket(destinationBucket)
                .destinationKey(destinationKey)
                .build();

        CopyRequest copyRequest = CopyRequest.builder()
                .copyObjectRequest(copyObjectRequest)
                .build();

        Copy copy = transferManager.copy(copyRequest);

        CompletedCopy completedCopy = copy.completionFuture().join();
        return completedCopy.response().copyObjectResult().eTag();
    }
```

**注記**  
S3 Transfer Manager でクロスリージョンコピーを実行するには、次のスニペットに示すように、CRT AWS ベースの S3 クライアントビルダー`crossRegionAccessEnabled`で を有効にします。  

```
S3AsyncClient s3AsyncClient = S3AsyncClient.crtBuilder()
                .crossRegionAccessEnabled(true)
                .build();

S3TransferManager transferManager = S3TransferManager.builder()
                .s3Client(s3AsyncClient)
                .build();
```

### インポート
<a name="transfer-manager-copy-import"></a>

```
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.model.CopyObjectRequest;
import software.amazon.awssdk.transfer.s3.S3TransferManager;
import software.amazon.awssdk.transfer.s3.model.CompletedCopy;
import software.amazon.awssdk.transfer.s3.model.Copy;
import software.amazon.awssdk.transfer.s3.model.CopyRequest;

import java.util.UUID;
```

## ローカルディレクトリを S3 バケットにアップロードする
<a name="transfer-manager-upload_directory"></a>

次の例は、ローカルディレクトリを S3 にアップロードする方法を示しています。

まず、`S3TransferManager` インスタンスの [uploadDirectory](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/S3TransferManager.html#uploadDirectory(software.amazon.awssdk.transfer.s3.model.UploadDirectoryRequest)) メソッドを呼び出し、[UploadDirectoryRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/UploadDirectoryRequest.html) を渡します。

[DirectoryUpload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/DirectoryUpload.html) オブジェクトはアップロードプロセスを表し、リクエストが完了すると [CompletedDirectoryUpload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CompletedDirectoryUpload.html) を生成します。`CompleteDirectoryUpload` オブジェクトは、どのファイルが転送に失敗したかなど、転送の結果に関する情報を含めます。

```
    public Integer uploadDirectory(S3TransferManager transferManager,
            URI sourceDirectory, String bucketName) {
        DirectoryUpload directoryUpload = transferManager.uploadDirectory(UploadDirectoryRequest.builder()
                .source(Paths.get(sourceDirectory))
                .bucket(bucketName)
                .build());

        CompletedDirectoryUpload completedDirectoryUpload = directoryUpload.completionFuture().join();
        completedDirectoryUpload.failedTransfers()
                .forEach(fail -> logger.warn("Object [{}] failed to transfer", fail.toString()));
        return completedDirectoryUpload.failedTransfers().size();
    }
```

### インポート
<a name="transfer-manager-upload_directory-import"></a>

```
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.services.s3.model.ObjectIdentifier;
import software.amazon.awssdk.transfer.s3.S3TransferManager;
import software.amazon.awssdk.transfer.s3.model.CompletedDirectoryUpload;
import software.amazon.awssdk.transfer.s3.model.DirectoryUpload;
import software.amazon.awssdk.transfer.s3.model.UploadDirectoryRequest;

import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Paths;
import java.util.UUID;
```

## ローカルディレクトリへの S3 バケットオブジェクトのダウンロード
<a name="transfer-manager-download_directory"></a>

次の例に示すように、S3 バケットのオブジェクトをローカルディレクトリにダウンロードできます。

S3 バケット内のオブジェクトをローカルディレクトリにダウンロードするには、まず Transfer Manager の [downloadDirectory](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/S3TransferManager.html#downloadDirectory(software.amazon.awssdk.transfer.s3.model.DownloadDirectoryRequest)) メソッドを呼び出し、[DownloadDirectoryRequest](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/DownloadDirectoryRequest.html) を渡します。

[DirectoryDownload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/DirectoryDownload.html) オブジェクトはダウンロードプロセスを表し、リクエストが完了すると [CompletedDirectoryDownload](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/transfer/s3/model/CompletedDirectoryDownload.html) を生成します。`CompleteDirectoryDownload` オブジェクトは、どのファイルが転送に失敗したかなど、転送の結果に関する情報を含めます。

```
    public Integer downloadObjectsToDirectory(S3TransferManager transferManager,
            URI destinationPathURI, String bucketName) {
        DirectoryDownload directoryDownload = transferManager.downloadDirectory(DownloadDirectoryRequest.builder()
                .destination(Paths.get(destinationPathURI))
                .bucket(bucketName)
                .build());
        CompletedDirectoryDownload completedDirectoryDownload = directoryDownload.completionFuture().join();

        completedDirectoryDownload.failedTransfers()
                .forEach(fail -> logger.warn("Object [{}] failed to transfer", fail.toString()));
        return completedDirectoryDownload.failedTransfers().size();
    }
```

### インポート
<a name="transfer-manager-download_directory-import"></a>

```
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.model.ObjectIdentifier;
import software.amazon.awssdk.transfer.s3.S3TransferManager;
import software.amazon.awssdk.transfer.s3.model.CompletedDirectoryDownload;
import software.amazon.awssdk.transfer.s3.model.DirectoryDownload;
import software.amazon.awssdk.transfer.s3.model.DownloadDirectoryRequest;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
```

## 完全な例を見る
<a name="transfer-manager-example-location"></a>

GitHub には、このページのすべての例の[完全なコードが含まれています](https://github.com/awsdocs/aws-doc-sdk-examples/tree/d73001daea05266eaa9e074ccb71b9383832369a/javav2/example_code/s3/src/main/java/com/example/s3/transfermanager)。

# S3 イベント通知の使用
<a name="examples-s3-event-notifications"></a>

バケット内のアクティビティのモニタリングに向けて、Amazon S3 は特定のイベントが発生したときに通知を送信できます。Amazon S3 ユーザーガイドには、[バケットが送信できる通知](https://docs.aws.amazon.com/AmazonS3/latest/userguide/EventNotifications.html#notification-how-to-overview)に関する情報が記載されています。

SDK for Java を使用して、4 つの送信先にイベントを送信するようにバケットを設定できます。
+ Amazon Simple Notification Service トピック
+ Amazon Simple Queue Service キュー
+ AWS Lambda 関数
+ Amazon EventBridge

EventBridge にイベントを送信するようにバケットを設定すると、同じイベントを複数の送信先にファンアウトするように EventBridge ルールを設定できます。最初の 3 つの送信先のいずれかに直接送信するようにバケットを設定する場合、イベントごとに指定できる送信先タイプは 1 つだけです。

次のセクションでは、SDK for Java を使用してバケットを設定し、Amazon SQS キューと EventBridge の 2 つの送信先に S3 イベント通知を送信する方法について説明します。

最後のセクションでは、S3 イベント通知 API を使用して、オブジェクト指向の方法で通知を使用する方法を示します。

## 送信先に直接送信するようにバケットを設定する
<a name="s3-event-conf-bucket-direct"></a>

次の例では、*オブジェクトの作成*イベントまたは*オブジェクトのタグ付け*イベントがバケットに対して発生したときに通知を送信するようにバケットを設定します。

```
static void processS3Events(String bucketName, String queueArn) {
    // Configure the bucket to send Object Created and Object Tagging notifications to an existing SQS queue.
    s3Client.putBucketNotificationConfiguration(b -> b
            .notificationConfiguration(ncb -> ncb
                    .queueConfigurations(qcb -> qcb
                            .events(Event.S3_OBJECT_CREATED, Event.S3_OBJECT_TAGGING)
                            .queueArn(queueArn)))
                    .bucket(bucketName)
    );
}
```

上記のコードは、2 種類のイベントを受信するように 1 つのキューを設定します。`queueConfigurations` メソッドを使用すると、必要に応じて複数のキューの送信先を設定できるため、便利です。また、 `notificationConfiguration` メソッドでは、1 つ以上の Amazon SNS トピックや 1 つ以上の Lambda 関数など、追加の送信先を設定できます。次のスニペットは、2 つのキューと 3 種類の送信先を含む例を示しています。

```
s3Client.putBucketNotificationConfiguration(b -> b
                .notificationConfiguration(ncb -> ncb
                        .queueConfigurations(qcb -> qcb
                                .events(Event.S3_OBJECT_CREATED, Event.S3_OBJECT_TAGGING)
                                .queueArn(queueArn), 
                                qcb2 -> qcb2.<...>)
                        .topicConfigurations(tcb -> tcb.<...>)
                        .lambdaFunctionConfigurations(lfcb -> lfcb.<...>))
                        .bucket(bucketName)
        );
```

「Code Examples」の GitHub リポジトリには、S3 イベント通知をキューに直接送信するための[完全な例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/s3/src/main/java/com/example/s3/ProcessS3EventNotification.java)が記載されています。

## EventBridge に送信するようにバケットを設定する
<a name="s3-event-conf-bucket-eventbridge"></a>

次の例では、EventBridge に通知を送信するようにバケットを設定します。

```
public static String setBucketNotificationToEventBridge(String bucketName) {
    // Enable bucket to emit S3 Event notifications to EventBridge.
    s3Client.putBucketNotificationConfiguration(b -> b
            .bucket(bucketName)
            .notificationConfiguration(b1 -> b1
                    .eventBridgeConfiguration(SdkBuilder::build))
    .build());
```

EventBridge にイベントを送信するようにバケットを設定するときは、EventBridge の送信先を指定するだけです。イベントのタイプや EventBridge がディスパッチする最終的な送信先を指定する必要はありません。Java SDK の EventBridge クライアントを使用して、最終的なターゲットとイベントタイプを設定します。

次のコードは、*オブジェクトの作成*イベントをトピックとキューにファンアウトするように EventBridge を設定する方法を示しています。

```
   public static String configureEventBridge(String topicArn, String queueArn) {
        try {
            // Create an EventBridge rule to route Object Created notifications.
            PutRuleRequest putRuleRequest = PutRuleRequest.builder()
                    .name(RULE_NAME)
                    .eventPattern("""
                            {
                              "source": ["aws.s3"],
                              "detail-type": ["Object Created"],
                              "detail": {
                                "bucket": {
                                  "name": ["%s"]
                                }
                              }
                            }
                            """.formatted(bucketName))
                    .build();

            // Add the rule to the default event bus.
            PutRuleResponse putRuleResponse = eventBridgeClient.putRule(putRuleRequest)
                    .whenComplete((r, t) -> {
                        if (t != null) {
                            logger.error("Error creating event bus rule: " + t.getMessage(), t);
                            throw new RuntimeException(t.getCause().getMessage(), t);
                        }
                        logger.info("Event bus rule creation request sent successfully. ARN is: {}", r.ruleArn());
                    }).join();

            // Add the existing SNS topic and SQS queue as targets to the rule.
            eventBridgeClient.putTargets(b -> b
                    .eventBusName("default")
                    .rule(RULE_NAME)
                    .targets(List.of (
                            Target.builder()
                                    .arn(queueArn)
                                    .id("Queue")
                                    .build(),
                            Target.builder()
                                    .arn(topicArn)
                                    .id("Topic")
                                    .build())
                            )
                    ).join();
            return putRuleResponse.ruleArn();
        } catch (S3Exception e) {
            System.err.println(e.awsErrorDetails().errorMessage());
            System.exit(1);
        }
        return null;
    }
```

Java コードで EventBridge を使用するには、Maven `pom.xml` ファイルに `eventbridge` アーティファクトの依存関係を追加します。

```
<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>eventbridge</artifactId>
</dependency>
```

「Code Examples」の GitHub リポジトリには、S3 イベント通知を EventBridge に送信し、その後トピックとキューに送信するための[完全な例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/javav2/example_code/s3/src/main/java/com/example/s3/PutBucketS3EventNotificationEventBridge.java)が記載されています。

## S3 イベント通知 API を使用してイベントを処理する
<a name="s3-event-notification-read"></a>

送信先が S3 通知イベントを受信したら、S3 イベント通知 API を使用して、オブジェクト指向の方法でイベントを処理できます。S3 イベント通知 API を使用して、ターゲットに直接ディスパッチされるイベント通知 ([最初の例](#s3-event-conf-bucket-direct)を参照) を使用できますが、EventBridge 経由でルーティングされる通知は使用できません。バケットから EventBridge に送信される S3 イベント通知には、S3 イベント通知 API が現在対応していない[別の構造](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ev-events.html#ev-events-list)が含まれています。

### 依存関係を追加する
<a name="s3-event-notifications-dep"></a>

S3 イベント通知 API は、SDK for Java 2.x のバージョン 2.25.11 でリリースされました。

S3 イベント通知 API を使用するには、次のスニペットに示すように、必要な依存関係要素を Maven `pom.xml` に追加します。

```
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>bom</artifactId>
            <version>2.X.X1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>s3-event-notifications</artifactId>
    </dependency>
</dependencies>
```

1 [最新バージョン](https://central.sonatype.com/artifact/software.amazon.awssdk/bom)。

### `S3EventNotification` クラスを使用する
<a name="s3-event-notifications-use"></a>

#### JSON 文字列から `S3EventNotification` インスタンスを作成する
<a name="s3-event-notifications-use-from-json"></a>

JSON 文字列を `S3EventNotification` オブジェクトに変換するには、次の例に示すように、 `S3EventNotification` クラスの静的メソッドを使用します。

```
import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification
import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotificationRecord
import software.amazon.awssdk.services.sqs.model.Message; 

public class S3EventNotificationExample {
    ...
    
    void receiveMessage(Message message) {
       // Message received from SQSClient.
       String sqsEventBody = message.body();
       S3EventNotification s3EventNotification = S3EventNotification.fromJson(sqsEventBody);
    
       // Use getRecords() to access all the records in the notification.                                                                                                       
       List<S3EventNotificationRecord> records = s3EventNotification.getRecords();   
    
        S3EventNotificationRecord record = records.stream().findFirst();
        // Use getters on the record to access individual attributes.
        String awsRegion = record.getAwsRegion();
        String eventName = record.getEventName();
        String eventSource = record.getEventSource();                                                                                                   
    }
}
```

この例では、 `fromJson` メソッドは JSON 文字列を `S3EventNotification` オブジェクトに変換します。JSON 文字列にフィールドが欠けている場合、対応する Java オブジェクトのフィールドの値は `null` になり、JSON に余分なフィールドが含まれていても無視されます。

イベント通知レコードの他の API は、`[S3EventNotificationRecord](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/eventnotifications/s3/model/S3EventNotificationRecord.html)` の API リファレンスに記載されています。

#### `S3EventNotification` インスタンスを JSON 文字列に変換する
<a name="s3-event-notifications-use-to-json"></a>

次の例に示すように、 `toJson` (または `toJsonPretty`) メソッドを使用して、`S3EventNotification` オブジェクトを JSON 文字列に変換します。

```
import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification

public class S3EventNotificationExample {
    ...

    void toJsonString(S3EventNotification event) {

        String json = event.toJson();
        String jsonPretty = event.toJsonPretty();

        System.out.println("JSON: " + json);
        System.out.println("Pretty JSON: " + jsonPretty);
    }
}
```

`GlacierEventData`、`ReplicationEventData`、`IntelligentTieringEventData`、および `LifecycleEventData` のフィールドは、`null` の場合は JSON から除外されます。他の `null` フィールドは `null` としてシリアル化されます。

S3 オブジェクトタグ付けイベントの `toJsonPretty` メソッドの出力例を次に示します。

```
{
  "Records" : [ {
    "eventVersion" : "2.3",
    "eventSource" : "aws:s3",
    "awsRegion" : "us-east-1",
    "eventTime" : "2024-07-19T20:09:18.551Z",
    "eventName" : "ObjectTagging:Put",
    "userIdentity" : {
      "principalId" : "AWS:XXXXXXXXXXX"
    },
    "requestParameters" : {
      "sourceIPAddress" : "XXX.XX.XX.XX"
    },
    "responseElements" : {
      "x-amz-request-id" : "XXXXXXXXXXXX",
      "x-amz-id-2" : "XXXXXXXXXXXXX"
    },
    "s3" : {
      "s3SchemaVersion" : "1.0",
      "configurationId" : "XXXXXXXXXXXXX",
      "bucket" : {
        "name" : "amzn-s3-demo-bucket",
        "ownerIdentity" : {
          "principalId" : "XXXXXXXXXXX"
        },
        "arn" : "arn:aws:s3:::XXXXXXXXXX"
      },
      "object" : {
        "key" : "akey",
        "size" : null,
        "eTag" : "XXXXXXXXXX",
        "versionId" : null,
        "sequencer" : null
      }
    }
  } ]
}
```

GitHub には、API を使用して Amazon SQS キューによって受信された通知を使用する方法を示す[完全な例](https://github.com/awsdocs/aws-doc-sdk-examples/blob/75c3daadf750406156fc87fa30ee499a206b4a36/javav2/example_code/s3/src/main/java/com/example/s3/ProcessS3EventNotification.java#L117)があります。

## Java ライブラリを使用して Lambda で S3 イベントを処理する: AWS SDK for Java 2.x および `aws-lambda-java-events`
<a name="s3-event-notif-processing-options"></a>

SDK for Java 2.x を使用して Lambda 関数で Amazon S3 イベント通知を処理する代わりに、バージョン 3.x.x. AWS `[aws-lambda-java-events](https://github.com/aws/aws-lambda-java-libs/tree/main/aws-lambda-java-events)`の`aws-lambda-java-events`ライブラリを個別に維持し、独自の依存要件があります。`aws-lambda-java-events` ライブラリは Lambda 関数の S3 イベントでのみ動作しますが、SDK for Java 2.x は Lambda 関数、Amazon SNS、Amazon SQS の S3 イベントで動作します。

どちらのアプローチも、オブジェクト指向の方法で JSON のイベント通知ペイロードをモデル化し、類似した API を提供します。次の表は、2 つのアプローチの使用における顕著な違いを示しています。


****  

|  | AWS SDK for Java | aws-lambda-java-events ライブラリ | 
| --- | --- | --- | 
| パッケージの命名 |  `software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification`  | com.amazonaws.services.lambda.runtime.events.models.s3.S3EventNotification | 
| RequestHandler パラメータ |  Lambda 関数の `RequestHandler` 実装を記述して JSON 文字列を受け取ります。 <pre>import com.amazonaws.services.lambda.runtime.Context;<br />import com.amazonaws.services.lambda.runtime.RequestHandler;<br />import software.amazon.awssdk.eventnotifications.s3.model.S3EventNotification;<br /><br />public class Handler implements RequestHandler<String, String> {<br /><br />    @Override<br />        public String handleRequest(String jsonS3Event, Context context) {<br />            S3EventNotification s3Event = S3EventNotification<br />                                             .fromJson(jsonS3Event);<br />            // Work with the s3Event object.        <br />            ...<br />    }<br />}</pre>  | Lambda 関数の RequestHandler 実装を記述して S3Event オブジェクトを受け取ります。<pre>import com.amazonaws.services.lambda.runtime.Context;<br />import com.amazonaws.services.lambda.runtime.RequestHandler;<br />import com.amazonaws.services.lambda.runtime.events.S3Event;<br /><br />public class Handler implements RequestHandler<S3Event, String> {<br /><br />    @Override<br />        public String handleRequest(S3Event s3event, Context context) {<br />            // Work with the s3Event object.        <br />            ...<br />    }<br />}</pre> | 
| Maven の依存関係 |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>software.amazon.awssdk</groupId><br />            <artifactId>bom</artifactId><br />            <version>2.X.X</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <dependency><br />        <groupId>software.amazon.awssdk</groupId><br />        <artifactId>s3-event-notifications</artifactId><br />    </dependency><br />    <!-- Add other SDK dependencies that you need. --><br /></dependencies></pre>  |  <pre><dependencyManagement><br />    <dependencies><br />        <dependency><br />            <groupId>software.amazon.awssdk</groupId><br />            <artifactId>bom</artifactId><br />            <version>2.X.X</version><br />            <type>pom</type><br />            <scope>import</scope><br />        </dependency><br />    </dependencies><br /></dependencyManagement><br /><dependencies><br />    <!-- The following two dependencies are for the <br />         aws-lambda-java-events library. --><br />    <dependency><br />        <groupId>com.amazonaws</groupId><br />        <artifactId>aws-lambda-java-core</artifactId><br />        <version>1.2.3</version>     <br />    </dependency><br />    <dependency><br />        <groupId>com.amazonaws</groupId><br />        <artifactId>aws-lambda-java-events</artifactId><br />        <version>3.15.0</version><br />    </dependency><br />    <!-- Add other SDK dependencies that you need. --><br /></dependencies></pre>  | 