tarun kumar
tarun kumar

Reputation: 11

I am facing error when uploading an image to s3 bucket using form-data in postman. I am writing the lambda code in .NET

I am trying to upload an image to s3 using lambda in .NET. But facing the Timeout issue. Anyone help me with the correct lambda code.

I have used this code but it gives the timeout error. In my api-gateway I added the binary type multipart/form-data and added headers(Content-Type and Accept) too in the method request. This is the code

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Amazon.Lambda.Core;
using Amazon.Lambda.APIGatewayEvents;
using Amazon.S3;
using Amazon.S3.Model;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Net.Http.Headers;

[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace IdCardRequest
{
    public class Function
    {
        public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context)
        {
            context.Logger.LogLine("Function started.");

            try
            {
                // Validate request
                context.Logger.LogLine("Validating request...");
                if (request.HttpMethod != "POST" ||
                    !request.Headers.ContainsKey("Content-Type") ||
                    !request.Headers["Content-Type"].StartsWith("multipart/form-data"))
                {
                    context.Logger.LogLine("Invalid request method or content type.");
                    return new APIGatewayProxyResponse
                    {
                        StatusCode = 400,
                        Body = "Invalid request method or content type"
                    };
                }

                // Get boundary from content type
                context.Logger.LogLine("Getting boundary from content type...");
                var boundary = GetBoundary(request.Headers["Content-Type"]);
                var bodyBytes = request.IsBase64Encoded ?
                    Convert.FromBase64String(request.Body) :
                    Encoding.UTF8.GetBytes(request.Body);

                using var stream = new MemoryStream(bodyBytes);
                var reader = new MultipartReader(boundary, stream);

                string employeeEmail = null;
                string fileName = null;
                string contentType = null;
                byte[] fileBytes = null;

                // Process multipart sections
                context.Logger.LogLine("Processing multipart sections...");
                MultipartSection section;
                while ((section = await reader.ReadNextSectionAsync()) != null)
                {
                    var contentDisposition = section.GetContentDispositionHeader();

                    if (contentDisposition.Name == "employeeEmail")
                    {
                        using var memoryStream = new MemoryStream();
                        await section.Body.CopyToAsync(memoryStream);
                        employeeEmail = Encoding.UTF8.GetString(memoryStream.ToArray());
                        context.Logger.LogLine($"Extracted employeeEmail: {employeeEmail}");
                    }
                    else if (contentDisposition.Name == "image" && contentDisposition.FileName != null)
                    {
                        fileName = contentDisposition.FileName.Value.Trim('"');
                        contentType = section.ContentType;
                        context.Logger.LogLine($"Extracted file name: {fileName}, Content-Type: {contentType}");

                        using var memoryStream = new MemoryStream();
                        await section.Body.CopyToAsync(memoryStream);
                        fileBytes = memoryStream.ToArray();
                        context.Logger.LogLine($"File size: {fileBytes.Length} bytes");
                    }
                }

                // Validate required fields
                context.Logger.LogLine("Validating required fields...");
                if (string.IsNullOrEmpty(employeeEmail) || fileBytes == null)
                {
                    context.Logger.LogLine("Missing employeeEmail or image file.");
                    return new APIGatewayProxyResponse
                    {
                        StatusCode = 400,
                        Body = "Missing employeeEmail or image file"
                    };
                }

                // Upload to S3
                context.Logger.LogLine("Uploading file to S3...");
                var s3Client = new AmazonS3Client();
                var bucketName = "id-card-assets";

                if (string.IsNullOrEmpty(bucketName))
                {
                    context.Logger.LogLine("BUCKET_NAME environment variable is not set.");
                    return new APIGatewayProxyResponse
                    {
                        StatusCode = 500,
                        Body = "BUCKET_NAME environment variable is not set."
                    };
                }

                var key = $"{employeeEmail}/{Guid.NewGuid()}_{fileName}";

                using var fileStream = new MemoryStream(fileBytes);
                var putRequest = new Amazon.S3.Model.PutObjectRequest
                {
                    BucketName = bucketName,
                    Key = key,
                    InputStream = fileStream,
                    ContentType = contentType ?? "application/octet-stream"
                };

                context.Logger.LogLine($"Uploading to S3 bucket: {bucketName}, Key: {key}");
                var response = await s3Client.PutObjectAsync(putRequest);
                context.Logger.LogLine($"S3 upload response: {response.HttpStatusCode}");

                if (response.HttpStatusCode == System.Net.HttpStatusCode.OK)
                {
                    context.Logger.LogLine("File uploaded successfully.");
                    return new APIGatewayProxyResponse
                    {
                        StatusCode = 200,
                        Body = $"File uploaded successfully to: {key}",
                        Headers = new Dictionary<string, string> { { "Content-Type", "text/plain" } }
                    };
                }
                else
                {
                    context.Logger.LogLine($"S3 upload failed with status code: {response.HttpStatusCode}");
                    return new APIGatewayProxyResponse
                    {
                        StatusCode = 500,
                        Body = $"S3 upload failed with status code: {response.HttpStatusCode}"
                    };
                }
            }
            catch (AmazonS3Exception ex)
            {
                context.Logger.LogLine($"AmazonS3Exception: {ex.Message}");
                context.Logger.LogLine($"Error Code: {ex.ErrorCode}");
                context.Logger.LogLine($"Request ID: {ex.RequestId}");
                context.Logger.LogLine($"Status Code: {ex.StatusCode}");
                return new APIGatewayProxyResponse
                {
                    StatusCode = 500,
                    Body = $"AmazonS3Exception: {ex.Message}"
                };
            }
            catch (Exception ex)
            {
                context.Logger.LogLine($"Exception during S3 upload: {ex}");
                return new APIGatewayProxyResponse
                {
                    StatusCode = 500,
                    Body = $"Exception during S3 upload: {ex.Message}"
                };
            }
        }

        private string GetBoundary(string contentType)
        {
            if (contentType == null)
                throw new ArgumentNullException(nameof(contentType));

            var elements = contentType.Split(' ');
            foreach (var element in elements)
            {
                if (element.StartsWith("boundary="))
                {
                    return element.Substring("boundary=".Length).Trim('"');
                }
            }

            throw new InvalidOperationException("Boundary not found in content type");
        }
    }
}

I am able to see the logs, like the employeeEmail and details of the image, but when uploading it is taking time and giving timeout error.

Upvotes: -1

Views: 32

Answers (0)

Related Questions