Cloudianは、AWSのS3完全互換のAPIを持ったオブジェクトストレージです。
今回は、Python(boto3)で、オブジェクトストレージのファイル転送をしてみたいと思います。
S3 Transfers によるファイル転送処理 (ファイルのアップロード/ダウンロード)
boto3 には、より簡易に/より効率的にアップロード/ダウンロード操作を行うことができる S3
Transfers というモジュールが用意されています。
S3 Transfers は、以下のような機能を提供しています。
- 指定したファイルサイズを上回った際に、自動的にマルチパート転送に切り替わります。
- 並列処理でファイルのアップロード/ダウンロードを実行します。
- ネットワークの最大帯域幅に応じて、ファイルを転送します。
- 転送状況をモニタリングするために、転送の進捗状況をコールバックできます。
- ファイルのアップロード時に、リトライを実行します。
S3 Transfers のパラメータのデフォルト値には最適な値が設定されていますが、以下のパラメータ設定を変更することもできます。
- マルチパート閾値サイズ
- 並行ダウンロード処理の最大数
- 使用するネットワーク最大帯域幅
- ソケット・タイムアウト値
- リトライ回数
S3 Transfers のパラメータを変更するには、変更対象のパラメータの設定値を引数に指定して、
TransferConfig オブジェクトを作成します(事前に "boto3.s3.transfer.TransferConfig" をインポートする必要があります)
from boto3.s3.transfer import S3Transfer
from boto3.s3.transfer import TransferConfig
config = TransferConfig(
multipart_threshold = 8 * 1024 * 1024,
max_concurrency = 10,
multipart_chunksize = 8388608,
num_download_attempts = 10,
max_io_queue = 100
)
transfer = S3Transfer(client, config)
1. S3Transfer オブジェクトの作成
S3 Transfers の機能を利用するためには、まず S3Transfer オブジェクトを作成します。
事前に、boto3.s3.transfer.S3Transfer をインポートしておく必要があります。本書の例では、既に S3Transfer はインポート済みの状態になっています。
S3Transfer()の引数に、既に作成済みの S3Client オブジェクトを渡して S3Transfer オブジェクトを作成します。S3Client オブジェクトのみを引数として渡し S3 Transfers オブジェクトを作成した場合には、S3 Transfers のパラメータは全てデフォルト値が使用されます。
transfer = S3Transfer(client)
2. ファイルのアップロード / S3Transfer.upload_file()
S3 Transfers を使用して Cloudian にファイルをアップロードするには、 upload_file()を使用します。
extra_args 引数を設定して upload_file()を呼び出すこと により、アップロード時にオブジェクト(ファイル)の ACL を設定したり、メタデータを付加したり、 暗号化を行ったりできます。
シンプルなファイルのアップロード
以下の例では、ローカルにあるファイル「10mb.dat」を、 Cloudian のバケット「pythonbucket1」にキー「10mb.dat」を設定してアップロードして います。
transfer.upload_file('fileup/10mb.dat', 'pythonbucket1', '10mb.dat')
下図は、 upload_file()の使用例で Cloudian にアップロードしたファイルを Cloudant Mamagement Console(以下CMC) の オブジェクト画面から参照したものです。
アップロード時に ACL、メタデータ、暗号化を指定
以下の例では、ローカルにあるファイル「10mb.dat」を、Cloudian のバケット「pythonbucket1」にキー「10mb.dat」を指定し、extra_args を設定してオブジェク トの ACL には「public-read」、3 つのメタデータを付加して「AES256」でサーバーサイド暗号化するように指定してアップロードしています。
transfer.upload_file(
'fileup/10mb.dat', 'pythonbucket1', '10mb.dat',
extra_args={
'ACL': 'public-read',
'Metadata': {
'Purpose': 'boto3 demo',
'Engineer': 'yamahiro',
'Company': 'Networld'
},
'ServerSideEncryption': 'AES256'
}
)
upload_file()の extra_args パラメータ「ServerSideEncryption」を使用し、AES256 で サーバーサイド暗号化を行うように設定したので、ファイル名の先頭に「🔒」マークが表示され、このファイルが暗号化されていることが分かります。
また、下図のようにこのファイルのプロパティを開いてみると、extra_args パラメータの ACL で設定したように、このファイルのアクセス権に「パブリック:読み出し可能('ACL': 'public-read')」にチェックが入っていることが分かります。
3. ファイルのダウンロード / S3Transfer.download_file()
S3 Transfers を使用して Cloudian からファイルをダウンロードするには、 download_file()を使用します。extra_args 引数を設定して download_file()を呼び 出すことにより、ダウンロード時にオブジェクトのバージョン ID を指定したりすることができます。
以下の例では、バケット「pythonbucket1」に保存されているキー「10mb.dat」の最新 バージョンのオブジェクトをダウンロードしています。
バケット「pythonbucket1」のバージョニング機能が有効にされていた場合、この例ではバー ジョン ID を指定していないので“最新バージョンのオブジェクト”がダウンロードされます(バージョニ ング機能については、後述します)。
transfer.download_file('pythonbucket1', '10mb.dat', 'filelocal/10mb-local.dat')
バージョニング機能が有効な場合
以下の例では、バージョニング機能が有効化されているバケット「pythonbucket1ver」に保存されているキー「10mb.dat」の、バージョン ID が「fe14c26e-1662-4f8f-a754-06bdfcde1d5e」のオブジェクトをダウンロードしています。
transfer.download_file(
'pythonbucket1ver', '10mb.dat', 'filelocal/10mb-local.dat',
extra_args={'VersionId': 'fe14c26e-1662-4f8f-a754-06bdfcde1d5e'}
)
S3 Transfers を使用したファイルのアップロード/ダウンロード時には、マルチパート閾値サイ ズ(multipart_threshold)が設定されており、そのデフォルト値は「8,388,608 bytes(約 8MB)」になっています。
アップロード/ダウンロード対象のファイルサイズが 8MB よりも大きい場合、S3 Transfers は 自動的に複数のパーツにファイルを分割して同時並行で処理を実行します。
下図は大きなサイズのファイルを S3 Transfers でアップロードを行っているときの、CMC オブジェクト画面のスクリーンショットです。8MB よりも大きなファイルは、自動的にマルチパートアップロードが実行されていることが分かります。
※補足: get_object() を使用したファイルのダウンロード
S3Transfers オブジェクトの download_file()を使用したファイルのダウンロード以外に、低レベル API に対応する get_object() を使用してファイルのダウンロードを行うこともできます。
with open('filelocal/10mb-local.dat', 'wb') as f: f.write(client.get_object( Bucket='pythonbucket1ver', Key='10mb.dat', VersionId='fe14c26e-1662-4f8f-a754-06bdfcde1d5e' )['Body'].read() )
ただしこの場合、上記サンプルコードのように、S3Transfers オブジェクトを使用した方法よりも若干、 コードが複雑になります。同じ操作を実行するために複数の方法があることがありますので、適材適所で どの方法を使用するか決める必要があります。
まとめ
Python(boto3)で、ファイル転送(アップロード/ダウンロード)をしてみました。