0
Help us understand the problem. What are the problem?

posted at

updated at

Organization

[Cloudian #4] Python(boto3)で、オブジェクトストレージのファイル転送してみる

はじめに

Cloudianは、AWSのS3完全互換のAPIを持ったオブジェクトストレージです。
前回は、Python(boto3)で、バケットを新規作成してみました。

今回は、Python(boto3)で、オブジェクトストレージのファイル転送をしてみたいと思います。

S3 Transfers によるファイル転送処理 (ファイルのアップロード/ダウンロード)

boto3 には、より簡易に/より効率的にアップロード/ダウンロード操作を行うことができる S3
Transfers というモジュールが用意されています。

S3 Transfers は、以下のような機能を提供しています。

  • 指定したファイルサイズを上回った際に、自動的にマルチパート転送に切り替わります。
  • 並列処理でファイルのアップロード/ダウンロードを実行します。
  • ネットワークの最大帯域幅に応じて、ファイルを転送します。
  • 転送状況をモニタリングするために、転送の進捗状況をコールバックできます。
  • ファイルのアップロード時に、リトライを実行します。

S3 Transfers のパラメータのデフォルト値には最適な値が設定されていますが、以下のパラメータ設定を変更することもできます。
- マルチパート閾値サイズ
- 並行ダウンロード処理の最大数
- 使用するネットワーク最大帯域幅
- ソケット・タイムアウト値
- リトライ回数

S3 Transfers のパラメータを変更するには、変更対象のパラメータの設定値を引数に指定して、
TransferConfig オブジェクトを作成します(事前に "boto3.s3.transfer.TransferConfig" をインポートする必要があります)

import boto3

from boto3.s3.transfer import S3Transfer
from boto3.s3.transfer import TransferConfig

client = boto3.client(
    's3',
    endpoint_url='https://xxx.yyy.com'
)

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 のパラメータは全てデフォルト値が使用されます。

import boto3

from boto3.s3.transfer import S3Transfer
from boto3.s3.transfer import TransferConfig

client = boto3.client(
    's3',
    endpoint_url='https://xxx.yyy.com'
)

# ファイル転送オブジェクト作成
transfer = S3Transfer(client)

2. ファイルのアップロード / S3Transfer.upload_file()

S3 Transfers を使用して Cloudian にファイルをアップロードするには、 upload_file()を使用します。

extra_args 引数を設定して upload_file()を呼び出すこと により、アップロード時にオブジェクト(ファイル)の ACL を設定したり、メタデータを付加したり、 暗号化を行ったりできます。

シンプルなファイルのアップロード

以下の例では、ローカルにあるファイル「10mb.dat」を、 Cloudian のバケット「pythonbucket1」にキー「10mb.dat」を設定してアップロードして います。

test1.py
import boto3

from boto3.s3.transfer import S3Transfer
from boto3.s3.transfer import TransferConfig

client = boto3.client(
    's3',
    endpoint_url='https://xxx.yyy.com'
)

# ファイル転送オブジェクト作成
transfer = S3Transfer(client)

# ファイルのアップロード実行
transfer.upload_file('fileup/10mb.dat', 'pythonbucket1', '10mb.dat')

下図は、 upload_file()の使用例で Cloudian にアップロードしたファイルを Cloudant Mamagement Console(以下CMC) の オブジェクト画面から参照したものです。

3-3-2.png

アップロード時に ACL、メタデータ、暗号化を指定

以下の例では、ローカルにあるファイル「10mb.dat」を、Cloudian のバケット「pythonbucket1」にキー「10mb.dat」を指定し、extra_args を設定してオブジェク トの ACL には「public-read」、3 つのメタデータを付加して「AES256」でサーバーサイド暗号化するように指定してアップロードしています。

test2.py
import boto3

from boto3.s3.transfer import S3Transfer
from boto3.s3.transfer import TransferConfig

client = boto3.client(
    's3',
    endpoint_url='https://xxx.yyy.com'
)

# ファイル転送オブジェクト作成
transfer = S3Transfer(client)


# ファイルのアップロード実行
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 で サーバーサイド暗号化を行うように設定したので、ファイル名の先頭に「🔒」マークが表示され、このファイルが暗号化されていることが分かります。

3-3-3.png

また、下図のようにこのファイルのプロパティを開いてみると、extra_args パラメータの ACL で設定したように、このファイルのアクセス権に「パブリック:読み出し可能('ACL': 'public-read')」にチェックが入っていることが分かります。

3-3-4.png

3. ファイルのダウンロード / S3Transfer.download_file()

S3 Transfers を使用して Cloudian からファイルをダウンロードするには、 download_file()を使用します。extra_args 引数を設定して download_file()を呼び 出すことにより、ダウンロード時にオブジェクトのバージョン ID を指定したりすることができます。

以下の例では、バケット「pythonbucket1」に保存されているキー「10mb.dat」の最新 バージョンのオブジェクトをダウンロードしています。

バケット「pythonbucket1」のバージョニング機能が有効にされていた場合、この例ではバー ジョン ID を指定していないので“最新バージョンのオブジェクト”がダウンロードされます(バージョニ ング機能については、後述します)。

test3.py
import boto3

from boto3.s3.transfer import S3Transfer
from boto3.s3.transfer import TransferConfig

client = boto3.client(
    's3',
    endpoint_url='https://xxx.yyy.com'
)

# ファイル転送オブジェクト作成
transfer = S3Transfer(client)

# ファイルのダウンロード実行
transfer.download_file('pythonbucket1', '10mb.dat', 'filelocal/10mb-local.dat')

バージョニング機能が有効な場合

以下の例では、バージョニング機能が有効化されているバケット「pythonbucket1ver」に保存されているキー「10mb.dat」の、バージョン ID が「fe14c26e-1662-4f8f-a754-06bdfcde1d5e」のオブジェクトをダウンロードしています。

test4.py
import boto3

from boto3.s3.transfer import S3Transfer
from boto3.s3.transfer import TransferConfig

client = boto3.client(
    's3',
    endpoint_url='https://xxx.yyy.com'
)

# ファイル転送オブジェクト作成
transfer = S3Transfer(client)

# ファイルのダウンロード実行
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 よりも大きなファイルは、自動的にマルチパートアップロードが実行されていることが分かります。

3-3-5.png

※補足: 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 オブジェクトを使用した方法よりも若干、 コードが複雑になります。同じ操作を実行するために複数の方法があることがありますので、適材適所で どの方法を使用するか決める必要があります。

4. まとめ

Python(boto3)で、ファイル転送(アップロード/ダウンロード)をしてみました。

次回も、Pythonでオブジェクトストレージ/Cloudianをいろいろ操作していきたいと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
0
Help us understand the problem. What are the problem?