2020/10/12

[Python3]boto3を使ってS3にファイルをアップロード/ダウンロードする

pythonaws

概要

Python3 + boto3を使って、クライアントからアップロードしたファイルをS3にアップロードし
表示のためにS3からダウンロードする必要があったため実装を行いました。

この記事ではS3にアップロード&S3からダウンロードの部分を重点的にメモしています。

実施内容

bucketの作成

アプリケーションが扱うS3バケットを作成します。
(仮に以下の名前で作成したとします)

  • your-app

ポリシーの作成

以下の名前と内容で、IAMポリシーを作成します。このポリシーは作成したS3バケットのフルアクセスのみを持つIAMです。

  • s3-your-app-full-access
{
   "Version":"2012-10-17",
   "Statement":[
      {
         "Effect":"Allow",
         "Action": "s3:*",
          "Resource": [
              "arn:aws:s3:::your-app",
              "arn:aws:s3:::your-app/*"
          ]
      }
   ]
}

グループの作成

アプリケーションのIAMユーザーが所属するIAMグループを作成します
(仮に以下の名前で作成したとします)

  • your-app

このグループに先ほど作った、s3-your-app-full-accessのポリシーを付与しておきます。

ユーザーの作成

アプリケーションのIAMユーザーを作成します
(仮に以下の名前で作成したとします)

  • your-app

このユーザーを先ほど作ったグループに所属させます。
アクセスの種類 プログラムによるアクセス を選択してユーザーを作成し、アクセスキーIDやシークレットアクセスキーをメモしておきます。

Pythonの実装

install

poetry add boto3
[tool.poetry.dependencies]
boto3 = "^1.15.16"

Upload

import boto3

# 環境変数や、aws cliなどで設定している場合は、aws_access_key_id / aws_secret_access_key / region_nameなどの引数は不要です。
client = boto3.client(
    "s3",
    aws_access_key_id=settings.AWS_ACCESS_KEY_ID,          # 作成したIAMユーザーのアクセスキーIDが設定されています
    aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,  # 作成したIAMユーザーのシークレットアクセスキーが設定されています
    region_name=settings.AWS_REGION,                       # S3バケットのregionが設定されています
)
client.upload_fileobj(
    Fileobj=stream,
    Bucket="your-app",
    Key="path/to/s3/key"
)

上記の Fileobj=stream にはHTTP Requestでアップロードされたファイルを一時ファイルに出力し(画像だったので、pillowなどを使って最適化などを行った後、保存しています。)そのfile objectを引き渡しています。
デフォルメすると以下のような感じになります。

import tempfile

with tempfile.NamedTemporaryFile() as temp_image_file:
    # ここで、pillowなどを使って、temp_image_fileにデータを保存します。
    stream = temp_image_file
    client.upload_fileobj(
        Fileobj=stream,
        Bucket="your-app",
        Key="path/to/s3/key"
    )

Download

import boto3

# 環境変数や、aws cliなどで設定している場合は、aws_access_key_id / aws_secret_access_key / region_nameなどの引数は不要です。
client = boto3.client(
    "s3",
    aws_access_key_id=settings.AWS_ACCESS_KEY_ID,          # 作成したIAMユーザーのアクセスキーIDが設定されています
    aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,  # 作成したIAMユーザーのシークレットアクセスキーが設定されています
    region_name=settings.AWS_REGION,                       # S3バケットのregionが設定されています
)
client.download_fileobj(
    Bucket="your-app",
    Key="path/to/s3/key",
    Fileobj=stream,
)

上記の Fileobj=stream には一時ファイルを作成し、そのfile objectを引き渡しています。
デフォルメすると以下のような感じになります。

import tempfile

stream = tempfile.TemporaryFile()
client.download_fileobj(
    Bucket="your-app",
    Key="path/to/s3/key",
    Fileobj=stream,
)
stream.seek(0)  # これをしてカーソルを先頭に戻して、clientへ送信したりします

References

以下が参考になりました。

今回は以上になります。