AWS SDK for JAVA を使用し、S3オブジェクトをアップロード、ダウンロードするScalaプログラムを書いた。依存するプログラムですでにV1が使用されていたのでV1を使用した。
ダウンロード処理ではS3オブジェクトの内容が変更されたときのみダウンロードを実行する。
https://aws.amazon.com/jp/sdk-for-java/
https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/
ハマった箇所が2つあったのでまとめる。
基本的なアップロードとダウンロード
まず、S3オブジェクトのアップロードとダウンロードをサンプルを見ながら基本的な動作を実装した。
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/upload-objects.html
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/download-objects.html
アップロード処理については常に実行し、ダウンロードするときに前回のハッシュ値と見比べる方法で実装することにした。
ハッシュ値
オブジェクトのハッシュ値を取得する方法を調べる。
Content-MD5
とりあえずシステム定義のメタデータ一覧を確認する。
Content-MD5
がオブジェクトのハッシュ値のようだ。
しかし、いざAWS SDKで取得してみると空になっていた。アップロード時の整合性を確認するためにローカルで生成したハッシュ値を送信し、さらにオプションで保存してメタデータとして返せるようになると言うもののようだ。
ETag
厳密にはコンテンツのハッシュ値とは限らないのだが、今回の用途では ETag
が使用できる。Consoleでもこの値は確認できる。メタデータの一覧には記載されていないが、しっかりメタデータとして取得できるので利用する。
ネットワーク接続のクローズ
SDKでは getObject
によりオブジェクトを取得し、コンテンツは getContent
で InputStream
が、 メタデータは getObjectMetadata
で取得できるようだ。 getContent
のストリームは使い終わったら閉じろとあるのでそのように書いた。
ネットワーク接続は、すべてのデータを読み取るか、入力ストリームを閉じるまで開いたままになります。ストリーミングのコンテンツは可能な限り迅速に読み取ることをお勧めします。
しかし、すぐに接続数が多いとエラーになってしまった。getObject
の時点でネットワーク接続が開始され、ストリームを使い終わるかgetObject
で返されたS3Object
のclose
を呼び出すまで切断されないようだ。getObject
以外でメタデータを取得したいところだが、調べると getObjectMetadata
があったので使用する。
V2のドキュメントではこのメソッドはClientには見当たらなかったので、もしかするとV2では getObject
の挙動が違うかもしれない。
この AmazonS3
のgetObjectMetadata
を使うことで問題は解決した。