たそらぼ

日頃思ったこととかメモとか。

pythonでS3にメタデータをつけてファイルをアップする

S3へのファイルのアップロードを自動化したかったので、pythonからboto3を使って行う方法を調べた。

要件としては、
・ファイル(オブジェクト)を上げたい
・CacheControlなどメタデータをつけたい。

s3.Bucket("bucket_name").put_object()を使ってアップしたいのやが、
取れる引数に Body=b'bytes'|file って書いてあるのに、fileを上げてる人が全然いない。
文字列なんか上げてもおもんないやん!ということで頑張って調べた。

Credentialsの設定

まずはaws cliをインストールして.aws/credentialsを作成する。
詳細は下記を参考。
AWS S3にPythonで画像ファイルアップロードする方法 - Qiita


設定があっているか確認する。

#cliで操作するアカウントがちゃんとあってるか確認。
#コンソール画面>アカウントから、アカウント IDを表示して、一致するか見る。
aws sts get-caller-identity


これでboto3の認証を行う際に、.aws/credentialsを読んでやってくれる。
コード内にハードコードもできるが、うっかりGitに上げちゃって死亡パターンが多く、別ファイルに書くことで事故を防ぐ。
boto3.amazonaws.com

アップロード

boto3が未インストールの場合はpipで入れておく。

#cliで操作するアカウントがちゃんとあってるか確認。
pip install boto3


コードは下記の通り。
put_object()の引数はドキュメントを見て欲しい。
S3 — Boto 3 Docs 1.9.146 documentation

import boto3                                                                                                                   
 
# 設定値もろもろ
bucket_name = #"ファイルをアップしたいバケットの名前"
filepath = #アップしたいファイルのパス
s3filename = #S3上にファイルをアップした時の名前(キー)
 
#実行内容
s3 = boto3.resource('s3')
with open(filepath, 'rb') as body_file:
    response = s3.Bucket(bucket_name).put_object(Key = s3filename ,
                                                 Body = body_file,
                                                 CacheControl = "max-age=3600",
                                                 ContentType = 'zip')

できた。めでたい。
f:id:tasotasoso:20190113170529p:plain

ハマったとこ

メタデータをつけられる関数が、put_object()しか見当たらなかった。
 ファイルをアップするだけだと、upload_file()などでも簡単にできるが、まさかのメタデータ設定の引数が用意されてなかったのでめっちゃ困った。
boto3.amazonaws.com
 put_object()はメタデータ設定できることが分かったが、サンプルで転がってるコードはファイルではなく試しに文字列をアップしたった的なものしかなく、
 調べまくった結果、同じことで困っている人を発見した。
github.com
 openでファイルオブジェクトを作っておいて、Bodyで渡すとアップできた。
 openする時はバイナリモードで開いておかないとエラーに。

問題点

 アクセス権を付与はs3:PutObjectAclのIAMロールが適切であれば設定できるはずだが、どうしても上手くいかなかった。
特にCacheControlとかを付けるときに、アクセス権限を変えられないと意味ないので、引き続き検証する。
github.com
AWS SDK (Node.js) で S3 putObjectするときに気をつけること – hotchpotch