diff --git a/s3-lambda-resizing-dotnet/.gitignore b/s3-lambda-resizing-dotnet/.gitignore
new file mode 100644
index 000000000..4507fc7d2
--- /dev/null
+++ b/s3-lambda-resizing-dotnet/.gitignore
@@ -0,0 +1,402 @@
+# Created by https://www.toptal.com/developers/gitignore/api/csharp
+# Edit at https://www.toptal.com/developers/gitignore?templates=csharp
+
+### Csharp ###
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+
+# End of https://www.toptal.com/developers/gitignore/api/csharp
\ No newline at end of file
diff --git a/s3-lambda-resizing-dotnet/ImageResize.sln b/s3-lambda-resizing-dotnet/ImageResize.sln
new file mode 100644
index 000000000..ffcd6c86c
--- /dev/null
+++ b/s3-lambda-resizing-dotnet/ImageResize.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.6.33815.320
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageResize", "ImageResize\ImageResize.csproj", "{FADD6CE5-EDF7-4BFE-B8F5-E84CD788D6DE}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {FADD6CE5-EDF7-4BFE-B8F5-E84CD788D6DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FADD6CE5-EDF7-4BFE-B8F5-E84CD788D6DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FADD6CE5-EDF7-4BFE-B8F5-E84CD788D6DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FADD6CE5-EDF7-4BFE-B8F5-E84CD788D6DE}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {3B666636-4024-4B31-80A6-CB25C208D7F9}
+ EndGlobalSection
+EndGlobal
diff --git a/s3-lambda-resizing-dotnet/ImageResize/Function.cs b/s3-lambda-resizing-dotnet/ImageResize/Function.cs
new file mode 100644
index 000000000..5724c587f
--- /dev/null
+++ b/s3-lambda-resizing-dotnet/ImageResize/Function.cs
@@ -0,0 +1,128 @@
+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[] fileExtensions = 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 (!fileExtensions.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);
+ var destinationBucket = Environment.GetEnvironmentVariable("DESTINATION_BUCKET_NAME");
+ await S3Client.PutObjectAsync(new PutObjectRequest
+ {
+ BucketName = destinationBucket,
+ 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;
+ }
+ }
+}
\ No newline at end of file
diff --git a/s3-lambda-resizing-dotnet/ImageResize/ImageResize.csproj b/s3-lambda-resizing-dotnet/ImageResize/ImageResize.csproj
new file mode 100644
index 000000000..9dd47ae3e
--- /dev/null
+++ b/s3-lambda-resizing-dotnet/ImageResize/ImageResize.csproj
@@ -0,0 +1,20 @@
+
+
+ net6.0
+ enable
+ enable
+ true
+ Lambda
+
+ true
+
+ true
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/s3-lambda-resizing-dotnet/ImageResize/Properties/launchSettings.json b/s3-lambda-resizing-dotnet/ImageResize/Properties/launchSettings.json
new file mode 100644
index 000000000..e6144efbb
--- /dev/null
+++ b/s3-lambda-resizing-dotnet/ImageResize/Properties/launchSettings.json
@@ -0,0 +1,10 @@
+{
+ "profiles": {
+ "Mock Lambda Test Tool": {
+ "commandName": "Executable",
+ "commandLineArgs": "--port 5050",
+ "workingDirectory": ".\\bin\\$(Configuration)\\net6.0",
+ "executablePath": "%USERPROFILE%\\.dotnet\\tools\\dotnet-lambda-test-tool-6.0.exe"
+ }
+ }
+}
\ No newline at end of file
diff --git a/s3-lambda-resizing-dotnet/ImageResize/aws-lambda-tools-defaults.json b/s3-lambda-resizing-dotnet/ImageResize/aws-lambda-tools-defaults.json
new file mode 100644
index 000000000..6ce1ffef1
--- /dev/null
+++ b/s3-lambda-resizing-dotnet/ImageResize/aws-lambda-tools-defaults.json
@@ -0,0 +1,26 @@
+
+{
+ "Information" : [
+ "This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.",
+ "To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.",
+ "dotnet lambda help",
+ "All the command line options for the Lambda command can be specified in this file."
+ ],
+ "profile" : "default",
+ "region" : "us-east-1",
+ "configuration" : "Release",
+ "function-runtime" : "dotnet6",
+ "function-memory-size" : 256,
+ "function-timeout" : 30,
+ "function-handler" : "ImageResize::ImageResize.Function::FunctionHandler",
+ "framework" : "net6.0",
+ "function-name" : "ImageResize",
+ "package-type" : "Zip",
+ "function-role" : "arn:aws:iam::595982400875:role/ImageResizeLambdaRole",
+ "function-architecture" : "x86_64",
+ "function-subnets" : "",
+ "function-security-groups" : "",
+ "tracing-mode" : "PassThrough",
+ "environment-variables" : "",
+ "image-tag" : ""
+}
\ No newline at end of file
diff --git a/s3-lambda-resizing-dotnet/README.md b/s3-lambda-resizing-dotnet/README.md
new file mode 100644
index 000000000..b267dd1c9
--- /dev/null
+++ b/s3-lambda-resizing-dotnet/README.md
@@ -0,0 +1,77 @@
+# AWS Amazon S3 to AWS Lambda - Create a Lambda function that resizes images uploaded to S3
+
+The SAM template deploys a .NET 6 Lambda function, an S3 bucket and the IAM resources required to run the application. A Lambda function consumes ObjectCreated
events from an Amazon S3 bucket. The function code checks the uploaded file is an image and creates a thumbnail version of the image in the same bucket.
+
+Learn more about this pattern at Serverless Land Patterns: [https://serverlessland.com/patterns/s3-lambda-dotnet](https://serverlessland.com/patterns/s3-lambda-dotnet)
+
+Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example.
+
+## Requirements
+
+* [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources.
+* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured
+* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
+* [AWS Serverless Application Model](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) (AWS SAM) installed
+* [.Net 6.0](https://dotnet.microsoft.com/en-us/download/dotnet/6.0)
+* [Docker](https://docs.docker.com/get-docker/) installed and running
+
+## Deployment Instructions
+
+1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository:
+ ```
+ git clone https://github.com/aws-samples/serverless-patterns
+ ```
+1. Change directory to the pattern directory:
+ ```
+ cd s3-lambda-dotnet
+ ```
+1. From the command line, use AWS SAM to build and deploy the AWS resources for the pattern as specified in the template.yml file:
+ ```
+ sam build
+ sam deploy --guided
+ ```
+1. During the prompts:
+ * Enter a stack name
+ * Enter the desired AWS Region
+ * Allow SAM CLI to create IAM roles with the required permissions.
+
+ Once you have run `sam deploy -guided` mode once and saved arguments to a configuration file (samconfig.toml), you can use `sam deploy` in future to use these defaults.
+
+1. Note the outputs from the SAM deployment process. These contain the resource names and/or ARNs which are used for testing.
+
+## How it works
+
+* Use the AWS CLI upload an image to S3
+* If the object is a .jpeg in the source bucket, the code creates a thumbnail and saves it to the destination bucket in a new folder, /thumbnails.
+* The code assumes that the destination bucket exists and is defined in the `template.yaml` file
+
+==============================================
+
+## Testing
+
+Run the following S3 CLI command to upload an image to the S3 bucket. Note, you must edit the {SourceBucketName} placeholder with the name of the S3 Bucket. This is provided in the stack outputs.
+
+```bash
+aws s3 cp './images/example.jpeg' s3://{BucketName}/example.jpeg
+```
+
+Run the following command to check that a new thumbnails folder has been created with a new version of the image.
+
+```bash
+aws s3 ls s3://{BucketName}/thumbnails
+```
+
+## Cleanup
+
+1. Delete the stack
+ ```bash
+ aws cloudformation delete-stack --stack-name STACK_NAME
+ ```
+1. Confirm the stack has been deleted
+ ```bash
+ aws cloudformation list-stacks --query "StackSummaries[?contains(StackName,'STACK_NAME')].StackStatus"
+ ```
+----
+Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+
+SPDX-License-Identifier: MIT-0
diff --git a/s3-lambda-resizing-dotnet/event.json b/s3-lambda-resizing-dotnet/event.json
new file mode 100644
index 000000000..f8486fe55
--- /dev/null
+++ b/s3-lambda-resizing-dotnet/event.json
@@ -0,0 +1,38 @@
+{
+ "Records": [
+ {
+ "eventVersion": "2.1",
+ "eventSource": "aws:s3",
+ "awsRegion": "us-east-1",
+ "eventTime": "2024-07-03T19:37:27.192Z",
+ "eventName": "ObjectCreated:Put",
+ "userIdentity": {
+ "principalId": "AWS:AIDAINPONIXQXHT3IKHL2"
+ },
+ "requestParameters": {
+ "sourceIPAddress": "205.255.255.255"
+ },
+ "responseElements": {
+ "x-amz-request-id": "D82B88E5F771F645",
+ "x-amz-id-2": "vlR7PnpV2Ce81l0PRw6jlUpck7Jo5ZsQjryTjKlc5aLWGVHPZLj5NeC6qMa0emYBDXOo6QBU0Wo="
+ },
+ "s3": {
+ "s3SchemaVersion": "1.0",
+ "configurationId": "828aa6fc-f7b5-4305-8584-487c791949c1",
+ "bucket": {
+ "name": "",
+ "ownerIdentity": {
+ "principalId": "A3I5XTEXAMAI3E"
+ },
+ "arn": "arn:aws:s3:::lambda-artifacts-deafc19498e3f2df"
+ },
+ "object": {
+ "key": "",
+ "size": 1305107,
+ "eTag": "b21b84d653bb07b05b1e6b33684dc11b",
+ "sequencer": "0C0F6F405D6ED209E1"
+ }
+ }
+ }
+ ]
+}
diff --git a/s3-lambda-resizing-dotnet/images/example.jpeg b/s3-lambda-resizing-dotnet/images/example.jpeg
new file mode 100644
index 000000000..031e7e132
Binary files /dev/null and b/s3-lambda-resizing-dotnet/images/example.jpeg differ
diff --git a/s3-lambda-resizing-dotnet/template.yaml b/s3-lambda-resizing-dotnet/template.yaml
new file mode 100644
index 000000000..93e4c2d02
--- /dev/null
+++ b/s3-lambda-resizing-dotnet/template.yaml
@@ -0,0 +1,70 @@
+AWSTemplateFormatVersion: '2010-09-09'
+Transform: AWS::Serverless-2016-10-31
+Description: >
+ (uksb-1tthgi812) (tag:s3-lambda-dotnet)
+ .NET Image resizing service
+
+# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
+Globals:
+ Function:
+ Tracing: PassThrough
+ Timeout: 10
+ Runtime: dotnet6
+
+Parameters:
+ SourceBucketName:
+ Type: String
+ # Pass your bucket name dynamically or change it here
+ Default: my-source-bucket-name
+ DestinationBucketName:
+ Type: String
+ # Pass your bucket name dynamically or change it here
+ Default: my-destination-bucket-name
+
+Resources:
+ SourceBucket:
+ Type: AWS::S3::Bucket
+ Properties:
+ BucketName: !Ref SourceBucketName
+
+ DestinationBucket:
+ Type: AWS::S3::Bucket
+ Properties:
+ BucketName: !Ref DestinationBucketName
+
+ ResizerFunction:
+ Type: AWS::Serverless::Function
+ Properties:
+ CodeUri: ImageResize/
+ Handler: ImageResize::ImageResize.Function::FunctionHandler
+ MemorySize: 2048
+ Environment:
+ Variables:
+ DESTINATION_BUCKET_NAME: !Ref DestinationBucketName
+ Policies:
+ - S3ReadPolicy:
+ BucketName: !Ref SourceBucketName
+ - S3CrudPolicy:
+ BucketName: !Ref DestinationBucketName
+ Events:
+ FileUpload:
+ Type: S3
+ Properties:
+ Bucket: !Ref SourceBucket
+ Events: s3:ObjectCreated:*
+ Filter:
+ S3Key:
+ Rules:
+ - Name: suffix
+ Value: '.jpeg'
+
+Outputs:
+ SourceBucketName:
+ Value: !Ref SourceBucketName
+ Description: S3 Bucket for object storage
+ DestinationBucketName:
+ Value: !Ref DestinationBucketName
+ Description: S3 destination Bucket for object storage
+ FunctionArn:
+ Value: !Ref ResizerFunction
+ Description: ResizerFunction function Arn
\ No newline at end of file
diff --git a/s3-lambda-resizing-node/README.md b/s3-lambda-resizing-node/README.md
new file mode 100644
index 000000000..8197d478d
--- /dev/null
+++ b/s3-lambda-resizing-node/README.md
@@ -0,0 +1,75 @@
+# AWS Amazon S3 to AWS Lambda - Create a Lambda function that resizes images uploaded to S3
+
+The SAM template deploys a Lambda function, an S3 bucket and the IAM resources required to run the application. A Lambda function consumes ObjectCreated
events from an Amazon S3 bucket. The Lambda code checks the uploaded file is an image and creates a thumbnail version of the image in the same bucket.
+
+Learn more about this pattern at Serverless Land Patterns: [https://serverlessland.com/patterns/s3-lambda](https://serverlessland.com/patterns/s3-lambda)
+
+Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example.
+
+## Requirements
+
+* [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources.
+* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured
+* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
+* [AWS Serverless Application Model](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html) (AWS SAM) installed
+
+## Deployment Instructions
+
+1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository:
+ ```
+ git clone https://github.com/aws-samples/serverless-patterns
+ ```
+1. Change directory to the pattern directory:
+ ```
+ cd s3-lambda
+ ```
+1. From the command line, use AWS SAM to build and deploy the AWS resources for the pattern as specified in the template.yml file:
+ ```
+ sam build
+ sam deploy --guided
+ ```
+1. During the prompts:
+ * Enter a stack name
+ * Enter the desired AWS Region
+ * Allow SAM CLI to create IAM roles with the required permissions.
+
+ Once you have run `sam deploy -guided` mode once and saved arguments to a configuration file (samconfig.toml), you can use `sam deploy` in future to use these defaults.
+
+1. Note the outputs from the SAM deployment process. These contain the resource names and/or ARNs which are used for testing.
+
+## How it works
+
+* Use the AWS CLI upload an image to S3
+* If the object is a .jpg or a .png, the code creates a thumbnail and saves it to the target bucket.
+* The code assumes that the destination bucket exists and its name is a concatenation of the source bucket name followed by the string -resized
+
+==============================================
+
+## Testing
+
+Run the following S3 CLI command to upload an image to the S3 bucket. Note, you must edit the {SourceBucketName} placeholder with the name of the S3 Bucket. This is provided in the stack outputs.
+
+```bash
+aws s3 cp './events/example.jpg' s3://{SourceBucketName}
+```
+
+Run the following command to check that a new version of the image has been created in the destination bucket.
+
+```bash
+aws s3 ls s3://{DestinationBucketName}
+```
+
+## Cleanup
+
+1. Delete the stack
+ ```bash
+ aws cloudformation delete-stack --stack-name STACK_NAME
+ ```
+1. Confirm the stack has been deleted
+ ```bash
+ aws cloudformation list-stacks --query "StackSummaries[?contains(StackName,'STACK_NAME')].StackStatus"
+ ```
+----
+Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+
+SPDX-License-Identifier: MIT-0
diff --git a/s3-lambda-resizing-node/events/event.json b/s3-lambda-resizing-node/events/event.json
new file mode 100644
index 000000000..f8486fe55
--- /dev/null
+++ b/s3-lambda-resizing-node/events/event.json
@@ -0,0 +1,38 @@
+{
+ "Records": [
+ {
+ "eventVersion": "2.1",
+ "eventSource": "aws:s3",
+ "awsRegion": "us-east-1",
+ "eventTime": "2024-07-03T19:37:27.192Z",
+ "eventName": "ObjectCreated:Put",
+ "userIdentity": {
+ "principalId": "AWS:AIDAINPONIXQXHT3IKHL2"
+ },
+ "requestParameters": {
+ "sourceIPAddress": "205.255.255.255"
+ },
+ "responseElements": {
+ "x-amz-request-id": "D82B88E5F771F645",
+ "x-amz-id-2": "vlR7PnpV2Ce81l0PRw6jlUpck7Jo5ZsQjryTjKlc5aLWGVHPZLj5NeC6qMa0emYBDXOo6QBU0Wo="
+ },
+ "s3": {
+ "s3SchemaVersion": "1.0",
+ "configurationId": "828aa6fc-f7b5-4305-8584-487c791949c1",
+ "bucket": {
+ "name": "",
+ "ownerIdentity": {
+ "principalId": "A3I5XTEXAMAI3E"
+ },
+ "arn": "arn:aws:s3:::lambda-artifacts-deafc19498e3f2df"
+ },
+ "object": {
+ "key": "",
+ "size": 1305107,
+ "eTag": "b21b84d653bb07b05b1e6b33684dc11b",
+ "sequencer": "0C0F6F405D6ED209E1"
+ }
+ }
+ }
+ ]
+}
diff --git a/s3-lambda-resizing-node/events/example.jpg b/s3-lambda-resizing-node/events/example.jpg
new file mode 100644
index 000000000..5a5e031e2
Binary files /dev/null and b/s3-lambda-resizing-node/events/example.jpg differ
diff --git a/s3-lambda-resizing-node/events/inputFile.txt b/s3-lambda-resizing-node/events/inputFile.txt
new file mode 100644
index 000000000..8dde042f4
--- /dev/null
+++ b/s3-lambda-resizing-node/events/inputFile.txt
@@ -0,0 +1,3 @@
+{
+ "IsHelloWorldExample": "Hello"
+}
\ No newline at end of file
diff --git a/s3-lambda-resizing-node/src/app.js b/s3-lambda-resizing-node/src/app.js
new file mode 100644
index 000000000..e5420f479
--- /dev/null
+++ b/s3-lambda-resizing-node/src/app.js
@@ -0,0 +1,53 @@
+/*! Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: MIT-0
+ */
+
+const { GetObjectCommand, PutObjectCommand, S3Client } = require("@aws-sdk/client-s3");
+const s3 = new S3Client({ region: process.env.AWS_REGION });
+
+const gm = require('gm')
+const NEW_SIZE_PX = 480
+
+// 1. Load the image from S3.
+// 2. Transform the image.
+// 3. Save the new image in another S3 bucket.
+
+exports.handler = async (event) => {
+ // console.log(JSON.stringify(event, null, 2))
+ const Key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " "))
+
+
+ // Read the object from S3
+ const commandGet = new GetObjectCommand({
+ Bucket: event.Records[0].s3.bucket.name,
+ Key
+ });
+ const s3Object = await s3.send(commandGet);
+
+ // Resize the image
+ const data = await resizeImage(s3Object.Body)
+
+ // Write to S3
+ const commandPut = new PutObjectCommand({
+ Bucket: process.env.DESTINATION_BUCKETNAME,
+ Key,
+ ContentType: 'image/jpeg',
+ Body: data,
+ });
+ const result = await s3.send(commandPut);
+ console.log('Write result: ', result)
+}
+
+
+
+// Resize - takes and returns a image buffer
+const resizeImage = async (buffer) => {
+ return new Promise((resolve, reject) => {
+ gm(buffer)
+ .resize(NEW_SIZE_PX, NEW_SIZE_PX)
+ .toBuffer('jpg', function (err, data) {
+ if (err) return reject(err)
+ resolve(data)
+ })
+ })
+}
\ No newline at end of file
diff --git a/s3-lambda-resizing-node/src/package.json b/s3-lambda-resizing-node/src/package.json
new file mode 100644
index 000000000..342766c18
--- /dev/null
+++ b/s3-lambda-resizing-node/src/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "resizer",
+ "version": "1.0.0",
+ "description": "",
+ "main": "app.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [],
+ "author": "James Beswick",
+ "license": "MIT-0",
+ "dependencies": {
+ "gm": "^1.25.0",
+ "@aws-sdk/client-s3": "^3.32.0"
+ }
+}
\ No newline at end of file
diff --git a/s3-lambda-resizing-node/template.yaml b/s3-lambda-resizing-node/template.yaml
new file mode 100644
index 000000000..b47762c9f
--- /dev/null
+++ b/s3-lambda-resizing-node/template.yaml
@@ -0,0 +1,60 @@
+AWSTemplateFormatVersion: '2010-09-09'
+Transform: AWS::Serverless-2016-10-31
+Description: Image resizing service (uksb-1tthgi812) (tag:s3-lambda)
+
+Parameters:
+ SourceBucketName:
+ Type: String
+ DestinationBucketName:
+ Type: String
+
+Resources:
+ ## S3 bucket
+ SourceBucket:
+ Type: AWS::S3::Bucket
+ Properties:
+ BucketName: !Ref SourceBucketName
+ DestinationBucket:
+ Type: AWS::S3::Bucket
+ Properties:
+ BucketName: !Ref DestinationBucketName
+
+ ## Lambda function
+ ResizerFunction:
+ Type: AWS::Serverless::Function
+ Properties:
+ CodeUri: src/
+ Handler: app.handler
+ Runtime: nodejs18.x
+ MemorySize: 2048
+ Layers:
+ - !Sub 'arn:aws:lambda:${AWS::Region}:175033217214:layer:graphicsmagick:2'
+ Policies:
+ - S3ReadPolicy:
+ BucketName: !Ref SourceBucketName
+ - S3CrudPolicy:
+ BucketName: !Ref DestinationBucketName
+ Environment:
+ Variables:
+ DESTINATION_BUCKETNAME: !Ref DestinationBucketName
+ Events:
+ FileUpload:
+ Type: S3
+ Properties:
+ Bucket: !Ref SourceBucket
+ Events: s3:ObjectCreated:*
+ Filter:
+ S3Key:
+ Rules:
+ - Name: suffix
+ Value: '.jpg'
+Outputs:
+ SourceBucketName:
+ Value: !Ref SourceBucketName
+ Description: S3 Bucket for object storage
+ DestinationBucketName:
+ Value: !Ref DestinationBucketName
+ Description: S3 destination Bucket for object storage
+ FunctionArn:
+ Value: !Ref ResizerFunction
+ Description: ResizerFunction function Arn
\ No newline at end of file