using System.IO;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.PixelFormats;
using Amazon.S3.Model;
using SixLabors.ImageSharp.Formats.Jpeg;
using Amazon.Lambda.Core;
using Amazon.Lambda.S3Events;
using Amazon.S3;
using Amazon.S3.Util;
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace ImageResize;
public class Function
{
IAmazonS3 S3Client { get; set; }
///
/// Default constructor. This constructor is used by Lambda to construct the instance. When invoked in a Lambda environment
/// the AWS credentials will come from the IAM role associated with the function and the AWS region will be set to the
/// region the Lambda function is executed in.
///
public Function()
{
S3Client = new AmazonS3Client();
}
///
/// Constructs an instance with a preconfigured S3 client. This can be used for testing outside of the Lambda environment.
///
///
public Function(IAmazonS3 s3Client)
{
this.S3Client = s3Client;
}
public async Task FunctionHandler(S3Event evnt, ILambdaContext context)
{
string[] fileExtentions = new string[] { ".jpg", ".jpeg" };
var s3Event = evnt.Records?[0].S3;
if (s3Event == null)
{
return null;
}
try
{
foreach (var record in evnt.Records)
{
LambdaLogger.Log("----> File: " + record.S3.Object.Key);
if (!fileExtentions.Contains(Path.GetExtension(record.S3.Object.Key).ToLower()))
{
LambdaLogger.Log("File Extension is not supported - " + s3Event.Object.Key);
continue;
}
string suffix = Path.GetExtension(record.S3.Object.Key).ToLower();
Stream imageStream = new MemoryStream();
using (var objectResponse = await S3Client.GetObjectAsync(record.S3.Bucket.Name, record.S3.Object.Key))
{
using (Stream responseStream = objectResponse.ResponseStream)
{
using (var image = Image.Load(responseStream))
{
// Create B&W thumbnail
image.Mutate(ctx => ctx.Grayscale().Resize(200, 200));
image.Save(imageStream, new JpegEncoder());
imageStream.Seek(0, SeekOrigin.Begin);
}
}
}
// Creating a new S3 ObjectKey for the thumbnails
string thumbnailObjectKey = null;
int endSlash = record.S3.Object.Key.ToLower().LastIndexOf("/");
if (endSlash > 0)
{
string S3ObjectName = record.S3.Object.Key.ToLower().Substring(endSlash + 1);
int beginSlash = 0;
if (endSlash > 0)
{
beginSlash = record.S3.Object.Key.ToLower().Substring(0, endSlash - 1).LastIndexOf("/");
if (beginSlash > 0)
{
thumbnailObjectKey =
record.S3.Object.Key.ToLower().Substring(0, beginSlash) +
"thumbnails/" +
S3ObjectName;
}
else
{
thumbnailObjectKey = "thumbnails/" + S3ObjectName;
}
}
}
else
{
thumbnailObjectKey = "thumbnails/" + record.S3.Object.Key.ToLower();
}
LambdaLogger.Log("----> Thumbnail file Key: " + thumbnailObjectKey);
await S3Client.PutObjectAsync(new PutObjectRequest
{
BucketName = record.S3.Bucket.Name,
Key = thumbnailObjectKey,
InputStream = imageStream
});
}
LambdaLogger.Log("Processed " + evnt.Records.Count.ToString());
return null;
}
catch (Exception e)
{
context.Logger.LogLine($"Error getting object {s3Event.Object.Key} from bucket {s3Event.Bucket.Name}");
context.Logger.LogLine($"Make sure they exist and your bucket is in the same region as this function");
context.Logger.LogLine(e.Message);
context.Logger.LogLine(e.StackTrace);
throw;
}
}
}