1
2

More than 3 years have passed since last update.

LambdaでS3オブジェクトに独自メタデータの追加・更新を行う

Posted at

はじめに

LambdaでS3オブジェクトを制御したかったので、オブジェクトに独自のメタデータ(ユーザ定義メタデータ)を追加・更新して対処した。
本文では、ユーザ定義メタデータについて、実際のソースと実行結果について記す。

ユーザ定義メタデータとは

Content-Lengthなどのオブジェクトの追加情報をメタデータという。
メタデータには2種類あり、主にAWSシステム上で制御されるシステムメタデータとユーザが独自で定義できるユーザ定義メタデータがある。
今回はファイルの上書き回数(メタデータ名をx-amz-meta-countとする)をユーザ定義メタデータとして定義する。

Lambdaソース

下記LambdaをCloudWatchEventsなどをトリガーとして実行する。
指定したバケット、ディレクトリ配下のファイルを取得し、そのファイルのメタデータにx-amz-meta-countがなければ追加する。
あれば、メタデータの値を+1する。
最後に追加更新した内容でファイルを上書き(copy_object())する。


import os
import json
import boto3
import pprint
import urllib.parse

if os.getenv("AWS_SAM_LOCAL"):
    s3Client = boto3.client(
        's3', endpoint_url='http://host.docker.internal:4572/'
    )
    s3Resource = boto3.resource(
        's3', endpoint_url="http://host.docker.internal:4572/")
else:
    s3Client = boto3.client('s3')
    s3Resource = boto3.resource('s3')


def lambda_handler(event, context):

    BUCKET_NAME = "test-ksatou-20200125"
    PREFIX = "input/"

    try:
        # ディレクトリ下のオブジェクト一覧を取得
        objs = s3Resource.Bucket(BUCKET_NAME).objects.filter(Prefix=PREFIX)
        for obj in objs:
            print("Key: " + obj.key)

            # オブジェクトのメタデータを取得
            headObj = s3Client.head_object(Bucket=BUCKET_NAME, Key=obj.key)
            # 上記で取得したメタデータから、ユーザ定義メタデータ(x-amz-meta-count)を取得する
            # ユーザ定義メタデータのキーの接頭辞は「x-amz-meta-」で始まる
            httpHeaders = headObj["ResponseMetadata"]["HTTPHeaders"]
            count = httpHeaders.get("x-amz-meta-count")
            orgEtag = httpHeaders.get("etag")
            contentType = headObj["ContentType"]

            # ユーザ定義メタデータ(x-amz-meta-count)を追加・更新して、ファイルを上書く
            # メタデータの追加・更新の際は、接頭辞「x-amz-meta-」は記述する必要はない
            # valueはstring型でなければならない
            metadata = headObj["Metadata"]
            metadata["count"] = "0" if count == None else str(
                int(count) + 1)
            s3Client.copy_object(Key=obj.key, Bucket=BUCKET_NAME,
                                 CopySource={
                                     "Bucket": BUCKET_NAME, "Key": obj.key},
                                 Metadata=metadata,
                                 ContentType=contentType,
                                 MetadataDirective="REPLACE",
                                 CopySourceIfMatch=orgEtag)
    except Exception as e:
        print(e)
        raise e

実行結果

実施前

x-amz-meta-countは付与されていない。
実施前.png

1回目

x-amz-meta-countが追加された。
1回目実施.png
1回目結果.png

2回目

x-amz-meta-countの値が+1された。
2回目実施.png
2回目結果.png

参考

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2