How to Read & Write QR Codes on AWS Lambda

Amazon Lambda Architecture Logo related to How to Read & Write QR Codes on AWS Lambda

This how-to article offers a detailed guide for setting up an AWS Lambda function with IronQR. In this tutorial, you will discover how to configure IronQR for reading and writing QR codes directly to an S3 bucket.

Installation

This article will use an S3 bucket, so the AWSSDK.S3 package is required.

Start using IronQR in your project today with a free trial.

First Step:
green arrow pointer

Create an AWS Lambda Project

With Visual Studio, creating a containerized AWS Lambda is an easy process:

  • Install the AWS Tookit for Visual Studio
  • Select an 'AWS Lambda Project (.NET Core - C#)'
  • Select a '.NET 8 (Container Image)' blueprint, then select 'Finish'.

Select container image

Add Package Dependencies

The IronQR library in .NET 8 operates on AWS Lambda without requiring additional dependencies. To configure it, modify the project's Dockerfile as shown below:

FROM public.ecr.aws/lambda/dotnet:8

# install necessary packages
RUN dnf update -y

WORKDIR /var/task

# This COPY command copies the .NET Lambda project's build artifacts from the host machine into the image. 
# The source of the COPY should match where the .NET Lambda project publishes its build artifacts. If the Lambda function is being built 
# with the AWS .NET Lambda Tooling, the `--docker-host-build-output-dir` switch controls where the .NET Lambda project
# will be built. The .NET Lambda project templates default to having `--docker-host-build-output-dir`
# set in the aws-lambda-tools-defaults.json file to "bin/Release/lambda-publish".
#
# Alternatively Docker multi-stage build could be used to build the .NET Lambda project inside the image.
# For more information on this approach checkout the project's README.md file.
COPY "bin/Release/lambda-publish"  .

Modify the FunctionHandler Code

This example creates a QR code, uploads it to an S3 bucket, and reads the newly generated QR code.

Before the try block, the file path is specified in the IronQrNuget directory, with a globally unique identifier (GUID) used as the file name. The Write method generates the QR code based on the provided value, and the resulting JPG byte array is then passed to the Read method for reading the QR code. This demonstrates that this AWS Lambda function is capable of reading QR codes.

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

// 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 IronQrNuGetAwsLambda;

public class Function
{
    private static readonly IAmazonS3 _s3Client = new AmazonS3Client(Amazon.RegionEndpoint.APSoutheast1);

    /// <param name="context">The ILambdaContext that provides methods for logging and describing the Lambda environment.</param>
    /// <returns></returns>
    public async Task FunctionHandler(ILambdaContext context)
    {
        IronQr.License.LicenseKey = "IronQR-MYLICENSE-KEY-1EF01";

        string bucketName = "deploymenttestbucket";
        string objectKey = $"IronQrNuget/{Guid.NewGuid()}.png";

        try
        {
            // Creating a qr is as simple as:
            var myQr = QrWriter.Write("12345");

            context.Logger.LogLine($"QR created.");

            // Upload the JPG to S3
            await UploadJpgToS3Async(bucketName, objectKey, myQr.Save().ExportBytesAsJpg());

            context.Logger.LogLine($"QR uploaded successfully to {bucketName}/{objectKey}");

            // Load the asset into QrImageInput
            QrImageInput imageInput = new QrImageInput(myQr.Save());

            // Create a QR Reader object
            QrReader reader = new QrReader();

            var resultFromByte = reader.Read(imageInput);

            foreach (var item in resultFromByte)
            {
                // Log the read value out
                context.Logger.LogLine($"QR value is = {item.Value}");
            }
        }
        catch (Exception e)
        {
            context.Logger.LogLine($"[ERROR] FunctionHandler: {e.Message}");
        }
    }
    // Function to upload the JPG file to S3
    private async Task UploadJpgToS3Async(string bucketName, string objectKey, byte[] pdfBytes)
    {
        using (var memoryStream = new MemoryStream(pdfBytes))
        {
            var request = new PutObjectRequest
            {
                BucketName = bucketName,
                Key = objectKey,
                InputStream = memoryStream,
                ContentType = "image/jpg",
            };

            await _s3Client.PutObjectAsync(request);
        }
    }
}
using Amazon.Lambda.Core;
using Amazon.S3;
using Amazon.S3.Model;
using IronQr;

// 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 IronQrNuGetAwsLambda;

public class Function
{
    private static readonly IAmazonS3 _s3Client = new AmazonS3Client(Amazon.RegionEndpoint.APSoutheast1);

    /// <param name="context">The ILambdaContext that provides methods for logging and describing the Lambda environment.</param>
    /// <returns></returns>
    public async Task FunctionHandler(ILambdaContext context)
    {
        IronQr.License.LicenseKey = "IronQR-MYLICENSE-KEY-1EF01";

        string bucketName = "deploymenttestbucket";
        string objectKey = $"IronQrNuget/{Guid.NewGuid()}.png";

        try
        {
            // Creating a qr is as simple as:
            var myQr = QrWriter.Write("12345");

            context.Logger.LogLine($"QR created.");

            // Upload the JPG to S3
            await UploadJpgToS3Async(bucketName, objectKey, myQr.Save().ExportBytesAsJpg());

            context.Logger.LogLine($"QR uploaded successfully to {bucketName}/{objectKey}");

            // Load the asset into QrImageInput
            QrImageInput imageInput = new QrImageInput(myQr.Save());

            // Create a QR Reader object
            QrReader reader = new QrReader();

            var resultFromByte = reader.Read(imageInput);

            foreach (var item in resultFromByte)
            {
                // Log the read value out
                context.Logger.LogLine($"QR value is = {item.Value}");
            }
        }
        catch (Exception e)
        {
            context.Logger.LogLine($"[ERROR] FunctionHandler: {e.Message}");
        }
    }
    // Function to upload the JPG file to S3
    private async Task UploadJpgToS3Async(string bucketName, string objectKey, byte[] pdfBytes)
    {
        using (var memoryStream = new MemoryStream(pdfBytes))
        {
            var request = new PutObjectRequest
            {
                BucketName = bucketName,
                Key = objectKey,
                InputStream = memoryStream,
                ContentType = "image/jpg",
            };

            await _s3Client.PutObjectAsync(request);
        }
    }
}
Imports Amazon.Lambda.Core
Imports Amazon.S3
Imports Amazon.S3.Model
Imports IronQr

' Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
<Assembly: LambdaSerializer(GetType(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))>

Namespace IronQrNuGetAwsLambda

	Public Class [Function]
		Private Shared ReadOnly _s3Client As IAmazonS3 = New AmazonS3Client(Amazon.RegionEndpoint.APSoutheast1)

		''' <param name="context">The ILambdaContext that provides methods for logging and describing the Lambda environment.</param>
		''' <returns></returns>
		Public Async Function FunctionHandler(ByVal context As ILambdaContext) As Task
			IronQr.License.LicenseKey = "IronQR-MYLICENSE-KEY-1EF01"

			Dim bucketName As String = "deploymenttestbucket"
			Dim objectKey As String = $"IronQrNuget/{Guid.NewGuid()}.png"

			Try
				' Creating a qr is as simple as:
				Dim myQr = QrWriter.Write("12345")

				context.Logger.LogLine($"QR created.")

				' Upload the JPG to S3
				Await UploadJpgToS3Async(bucketName, objectKey, myQr.Save().ExportBytesAsJpg())

				context.Logger.LogLine($"QR uploaded successfully to {bucketName}/{objectKey}")

				' Load the asset into QrImageInput
				Dim imageInput As New QrImageInput(myQr.Save())

				' Create a QR Reader object
				Dim reader As New QrReader()

				Dim resultFromByte = reader.Read(imageInput)

				For Each item In resultFromByte
					' Log the read value out
					context.Logger.LogLine($"QR value is = {item.Value}")
				Next item
			Catch e As Exception
				context.Logger.LogLine($"[ERROR] FunctionHandler: {e.Message}")
			End Try
		End Function
		' Function to upload the JPG file to S3
		Private Async Function UploadJpgToS3Async(ByVal bucketName As String, ByVal objectKey As String, ByVal pdfBytes() As Byte) As Task
			Using memoryStream As New MemoryStream(pdfBytes)
				Dim request = New PutObjectRequest With {
					.BucketName = bucketName,
					.Key = objectKey,
					.InputStream = memoryStream,
					.ContentType = "image/jpg"
				}

				Await _s3Client.PutObjectAsync(request)
			End Using
		End Function
	End Class
End Namespace
VB   C#

Increase Memory and Timeout

The memory allocation for the Lambda function depends on the size of the documents and the number processed simultaneously. As a starting point, set the memory to 512 MB and the timeout to 300 seconds in the aws-lambda-tools-defaults.json.

"function-memory-size" : 512,
"function-timeout" : 300

If the memory is insufficient, the program will raise the error: 'Runtime exited with error: signal: killed.' Increasing the memory size can help resolve this issue. For further guidance, check the troubleshooting article: AWS Lambda - Runtime Exited Signal: Killed.

Publish

To publish in Visual Studio, simply right-click the project and choose 'Publish to AWS Lambda...' Then, configure the required settings. For more information, visit the AWS website.

Try It Out!

You can activate the Lambda function either through the Lambda console or through Visual Studio.