AWS
C#
S3
lambda

AWS Lambda(C#)からS3へファイル作成して保存してみた

More than 1 year has passed since last update.

初めてLambdaを使っていた時に、いろいろはまりましたので、その経験をメモにしました。

開発環境

.Net Core
AWS Toolkit for Visual Studio

S3と連携

using Amazon.S3;
using Amazon.S3.Model;

だけでは使えないようです。
s3_using_error.png
Nugetで必要なパッケージをインストールする必要があります。

s3_nuget_import.png

install.png
これでエラーが消えました。
installed.png

S3にファイルを作成するコード

早速AWSのサンプルコードを参考し実装してみました。
AWS SDK for .NET を使用したオブジェクトのアップロード

using System;
using System.Threading.Tasks;

using Amazon.Lambda.Core;
using Amazon.S3;
using Amazon.S3.Model;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]

namespace AWSLambdaSample
{
    public class Function
    {
        /// <summary>
        /// A simple function that takes a string and does a ToUpper
        /// </summary>
        /// <param name="input"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public string FunctionHandler(string input, ILambdaContext context)
        {
            AmazonS3Client client = new AmazonS3Client(Amazon.RegionEndpoint.APNortheast1);

            PutObjectRequest request = new PutObjectRequest()
            {

                BucketName = "databucket-rest-datasource",
                Key = "hello.txt",
                ContentType = "text/plain",
                ContentBody = "Hello World!"
            };
            try {
                client.PutObjectAsync(request);
                return "OK";

            } catch (Exception e) {
                return e.ToString();
            }
        }
    }
}

LambdaにPublish

Publish to AWS
publishtoaws.png

uploadlambdafunction.png

ロールを選択し、Upload
roleset.png

Lambdaで実行

Input(特に利用してないので、ただのダミー)を入れて、Invokeしてみると
invoke.png
正常に通ったので、簡単だなと思いきや、S3のバケットに何も作成されませんでした。

s3bucket.png

うまくいかない理由

よくよく見ますと、参考したサンプルコードは「AWS SDK for .NET を使用したオブジェクトのアップロード」とのことで、Lambdaについて一言も言っていない。。。
使っているメソッドも

PutObjectResponse response2 = client.PutObject(request); 

なので、PutObjectAsyncではないです。そもそもAWSSDK.S3パッケージのAmazonS3ClientクラスにPutObjectメソッドが存在しませんでした。
なぜそうなのか調べてみたが、どこにも書いていないため、
非同期前提で設計されていると勝手に解釈しています。

もう一度S3と連携

using System;
using System.Threading.Tasks;

using Amazon.Lambda.Core;
using Amazon.S3;
using Amazon.S3.Model;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.Json.JsonSerializer))]

namespace AWSLambdaSample
{
    public class Function
    {
        /// <summary>
        /// A simple function that takes a string and does a ToUpper
        /// </summary>
        /// <param name="input"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task<string> FunctionHandler(string input, ILambdaContext context)
        {
            AmazonS3Client client = new AmazonS3Client(Amazon.RegionEndpoint.APNortheast1);

            PutObjectRequest request = new PutObjectRequest()
            {

                BucketName = "databucket-rest-datasource",
                Key = "hello.txt",
                ContentType = "text/plain",
                ContentBody = "Hello World!"
            };
            try {
                await client.PutObjectAsync(request);
                return "OK";

            } catch (Exception e) {
                return e.ToString();
            }
        }
    }
}

ハンドラーを非同期にして、もう一度Publish
同じ手順でLambdaを実行しますと、今度はファイルが作成されました。
okimage.png