LambdaでS3にある画像をDropbox Businessにアップロードするを改修し、
トリガーをS3アップロードに変更したときの個人メモ
(参考)チュートリアル: Amazon S3 トリガーを使用して Lambda 関数を呼び出す
ソース修正
- 以下のようにソースを改修
lambda_function.py
import os
import logging
import boto3
import urllib.parse
import base64
import requests
import json
# ログ設定
logger = logging.getLogger(__name__)
logger.setLevel(os.environ['LOG_LEVEL'])
# Dropbox設定
# ルートフォルダを指定
NAMESPACE_ID = os.environ['NAMESPACE_ID']
APP_KEY = os.environ['APP_KEY']
APP_SECRET = os.environ['APP_SECRET']
REFRESH_TOKEN = os.environ['REFRESH_TOKEN']
# S3から指定したバケット、フォルダ、ファイル名の画像を取得する
# 取得できる画像サイズはLambdaのメモリーに依存
# return:画像のバイナリデータ
def get_img_from_s3(bucket_name, file_path):
logger.debug('start get_img_from_s3()')
s3 = boto3.client('s3')
response = s3.get_object(Bucket=bucket_name, Key=file_path)
body = response['Body'].read()
logger.debug('end get_img_from_s3()')
return body
# リフレッシュトークンからアクセストークンを取得する
# return:アクセストークン
def get_token():
logger.debug('start get_token()')
data = {
'grant_type': 'refresh_token',
'refresh_token': REFRESH_TOKEN
}
response = requests.post('https://api.dropbox.com/oauth2/token', data=data, auth=(APP_KEY, APP_SECRET))
logger.info('response:' + json.dumps(response.json(),default=str))
access_token = response.json()['access_token']
logger.debug('access_token:' + access_token)
logger.debug('end get_token()')
return access_token
# 画像をDropboxにアップロードする
# img:画像のバイナリデータ
# return:アップロード結果
def upload_to_dropbox(access_token, img, file_path):
logger.debug('start upload_to_dropbox()')
arg = '{"path": "' + '/' + file_path + '","mode": "add","autorename": true,"mute": false,"strict_conflict": false}'
headers = {
'Authorization': 'Bearer ' + access_token,
'Dropbox-API-Arg': arg.encode("utf_8"),
'Content-Type': 'application/octet-stream',
'Dropbox-API-Path-Root': '{".tag": "namespace_id", "namespace_id": "' + NAMESPACE_ID + '"}',
}
response = requests.post('https://content.dropboxapi.com/2/files/upload', headers=headers, data=img)
logger.info('response:' + json.dumps(response.json(),default=str))
logger.debug('end upload_to_dropbox()')
return json.dumps(response,default=str)
def lambda_handler(event, context):
logger.debug('start lambda_handler()')
# S3設定
bucket_name = event['Records'][0]['s3']['bucket']['name']
logger.info('bucket_name:' + bucket_name)
# 画像ファイル情報
file_path = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')
logger.info('file_path:' + file_path)
img = get_img_from_s3(bucket_name, file_path)
access_token = get_token()
result = upload_to_dropbox(access_token, img, file_path)
logger.debug('end lambda_handler()')
return result
テストイベントJSON設定
- 以下のようにテストイベントJSONを設定
- バケット名とオブジェクトキー以外はテンプレートのまま利用
{
"Records": [
{
"eventVersion": "2.0",
"eventSource": "aws:s3",
"awsRegion": "us-west-2",
"eventTime": "1970-01-01T00:00:00.000Z",
"eventName": "ObjectCreated:Put",
"userIdentity": {
"principalId": "EXAMPLE"
},
"requestParameters": {
"sourceIPAddress": "127.0.0.1"
},
"responseElements": {
"x-amz-request-id": "EXAMPLE123456789",
"x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
},
"s3": {
"s3SchemaVersion": "1.0",
"configurationId": "testConfigRule",
"bucket": {
"name": "(バケット名)",
"ownerIdentity": {
"principalId": "EXAMPLE"
},
"arn": "arn:aws:s3:::example-bucket"
},
"object": {
"key": "image/escle.png",
"size": 1024,
"eTag": "0123456789abcdef0123456789abcdef",
"sequencer": "0A1B2C3D4E5F678901"
}
}
}
]
}
- Testを実行し、動作が改修前後で差異がないことを確認
トリガー設定
- 「トリガーを追加」を押下
- S3バケットを指定し、「追加」を押下
- 追加されたことを確認
動作確認
- 任意のフォルダにアップロード
- アップロードされたことを確認
- Lambdaのログを確認
- Lambdaが実行されたことを確認
- Dropboxにアップロードされたことを確認
感想
- テストイベントJSONを利用することで問題を切り分けながら改修できた
- 大量の画像がアップロードされたときの性能まわりは気になる
- エラー処理等も運用含めて考えていきたい