1

I am developing an AWS lambda function usign .NET core 2. This is my first time developing AWS lambda function using .NET. What I am trying to do now is so simple, read the existing file and save the file with new name (new name). Reading the file is working fine. But when I save the file using PutObjectRequest, it is giving me an error.

This is my code for the handler function

public async Task<string> FunctionHandler(S3Event evnt, ILambdaContext context)
      {
         var s3Event = evnt.Records?[0].S3;
         if(s3Event == null)
         {
            return null;
         }

         try
         {
            if(s3Event.Object.Key.ToLower().Contains("thumb"))
            {
               //Console.WriteLine("The image is already a thumb file");
               return "The file is aready a thumb image file";
            }

            string[] pathSegments = s3Event.Object.Key.Split('/');
            string eventCode = pathSegments[0];
            string userEmail = pathSegments[1];
            string filename = pathSegments[2];
            string extension = Path.GetExtension(filename); //.jpeg with "dot"
            string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(filename);

            using(var objectResponse = await this.S3Client.GetObjectAsync(s3Event.Bucket.Name, s3Event.Object.Key))
            {
               using(Stream responseStream = objectResponse.ResponseStream)
               {
                  //This code is throwing error
                  await this.S3Client.PutObjectAsync(new Amazon.S3.Model.PutObjectRequest
                  {
                     BucketName = s3Event.Bucket.Name,
                     Key = fileNameWithoutExtension + ".thumb" + extension,
                     InputStream = responseStream
                  });
               }
            }

            return "Thumbnail version of the image has been created";

         }
         catch(Exception e)
         {
            context.Logger.LogLine($"Error getting object {s3Event.Object.Key} from bucket {s3Event.Bucket.Name}. 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;
         }
      }

When I run the test function, it is giving me this error.

{
  "errorType": "AggregateException",
  "errorMessage": "One or more errors occurred. (Could not determine content length)",
  "stackTrace": [
    "at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)",
    "at lambda_method(Closure , Stream , Stream , LambdaContextInternal )"
  ],
  "cause": {
    "errorType": "AmazonS3Exception",
    "errorMessage": "Could not determine content length",
    "stackTrace": [
      "at Amazon.S3.Model.Internal.MarshallTransformations.PutObjectRequestMarshaller.GetStreamWithLength(Stream baseStream, Int64 hintLength)",
      "at Amazon.S3.Model.Internal.MarshallTransformations.PutObjectRequestMarshaller.Marshall(PutObjectRequest putObjectRequest)",
      "at Amazon.Runtime.Internal.Marshaller.PreInvoke(IExecutionContext executionContext)",
      "at Amazon.Runtime.Internal.Marshaller.InvokeAsync[T](IExecutionContext executionContext)",
      "at Amazon.Runtime.Internal.CallbackHandler.<InvokeAsync>d__9`1.MoveNext()",
      "--- End of stack trace from previous location where exception was thrown ---",
      "at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()",
      "at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)",
      "at Amazon.S3.Internal.AmazonS3ExceptionHandler.<InvokeAsync>d__1`1.MoveNext()",
      "--- End of stack trace from previous location where exception was thrown ---",
      "at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()",
      "at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)",
      "at Amazon.Runtime.Internal.ErrorCallbackHandler.<InvokeAsync>d__5`1.MoveNext()",
      "--- End of stack trace from previous location where exception was thrown ---",
      "at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()",
      "at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)",
      "at Amazon.Runtime.Internal.MetricsHandler.<InvokeAsync>d__1`1.MoveNext()",
      "--- End of stack trace from previous location where exception was thrown ---",
      "at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()",
      "at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)",
      "at AwsS3Lambda.Function.<FunctionHandler>d__10.MoveNext() in C:\\Users\\Acer\\Desktop\\MementoCSharp\\memento-dotnet\\AwsS3Lambda\\Function.cs:line 99"
    ]
  },
  "causes": [
    {
      "errorType": "AmazonS3Exception",
      "errorMessage": "Could not determine content length",
      "stackTrace": [
        "at Amazon.S3.Model.Internal.MarshallTransformations.PutObjectRequestMarshaller.GetStreamWithLength(Stream baseStream, Int64 hintLength)",
        "at Amazon.S3.Model.Internal.MarshallTransformations.PutObjectRequestMarshaller.Marshall(PutObjectRequest putObjectRequest)",
        "at Amazon.Runtime.Internal.Marshaller.PreInvoke(IExecutionContext executionContext)",
        "at Amazon.Runtime.Internal.Marshaller.InvokeAsync[T](IExecutionContext executionContext)",
        "at Amazon.Runtime.Internal.CallbackHandler.<InvokeAsync>d__9`1.MoveNext()",
        "--- End of stack trace from previous location where exception was thrown ---",
        "at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()",
        "at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)",
        "at Amazon.S3.Internal.AmazonS3ExceptionHandler.<InvokeAsync>d__1`1.MoveNext()",
        "--- End of stack trace from previous location where exception was thrown ---",
        "at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()",
        "at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)",
        "at Amazon.Runtime.Internal.ErrorCallbackHandler.<InvokeAsync>d__5`1.MoveNext()",
        "--- End of stack trace from previous location where exception was thrown ---",
        "at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()",
        "at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)",
        "at Amazon.Runtime.Internal.MetricsHandler.<InvokeAsync>d__1`1.MoveNext()",
        "--- End of stack trace from previous location where exception was thrown ---",
        "at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()",
        "at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)",
        "at AwsS3Lambda.Function.<FunctionHandler>d__10.MoveNext() in C:\\Users\\Acer\\Desktop\\MementoCSharp\\memento-dotnet\\AwsS3Lambda\\Function.cs:line 99"
      ]
    }
  ]
}

What is wrong and how can I solve it? How can I save a new file?

1 Answer 1

2

I would change:

await this.S3Client.PutObjectAsync(new Amazon.S3.Model.PutObjectRequest
{
    BucketName = s3Event.Bucket.Name,
    Key = fileNameWithoutExtension + ".thumb" + extension,
    InputStream = responseStream
});

to:

await this.S3Client.PutObjectAsync(new Amazon.S3.Model.PutObjectRequest
{
    BucketName = s3Event.Bucket.Name,
    Key = fileNameWithoutExtension + ".thumb" + extension,
    InputStream = responseStream,
    Headers.ContentLength = s3event.object.size
});

This tells S3 how large the object is that you're storing. When you get the actual thumbnail code working Headers.ContentLength will instead be the length of the thumbnail image.

Sign up to request clarification or add additional context in comments.

2 Comments

There is no such property as Headers.ContentLength in the PutRequestObject class. No Headers property.
You can set the content headers values like this: new PutObjectRequest { Headers = { ContentLength = responseStream.Length } };

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.