Attilio Gelosa
Attilio Gelosa

Reputation: 561

Upload a file on AWS S3 using pre-signed URL in .NET 6 (C#)

I'm trying to upload a file to an AWS S3 bucket using a pre-signed URL. I'm using the following code:

Uri output = GetPresignedUrl(amazonS3, awsPresignedUrlOptions);

using (FileStream tempInFileStream = new(tempFileName.LocalPath, FileMode.Open))
{
    using (HttpClient httpClient = new())
    {
        StreamContent streamContent = new(tempInFileStream);
        HttpResponseMessage response = httpClient
            .PutAsync(output, streamContent)
            .Result;

        response.EnsureSuccessStatusCode();
    }
}

The first line of code gets the pre-signed URL, and I'm sure it works because if I use the URL in Postman to try a PUT, it works fine (i.e., I'm able to upload the file).

My problem is in the HttpResponseMessage response = httpClient.PutAsync(output, streamContent).Result; line: executing the line, the software seems to do absolutely nothing and, after a period, raise an exception for the timeout.

Any suggestion?

EDIT

As suggested by @Yevhen Cherkes, I tried to use async code:

private static async void UploadAsync(Uri tempFileName, Uri output)
{
    try
    {
        using (FileStream tempInFileStream = new(tempFileName.LocalPath, FileMode.Open))
        {
            using (HttpClient httpClient = new())
            {
                StreamContent streamContent = new(tempInFileStream);
                HttpResponseMessage response = await httpClient
                    .PutAsync(output, streamContent);

                response.EnsureSuccessStatusCode();
            }
        }
    }
    catch (Exception e)
    {
        throw e;
    }
}

Called with this code:

Thread t = new Thread(() => UploadAsync(tempFileName, output));

t.Start();
t.Join();

The main thread correctly starts the sub-thread and waits to join, but when I tried to run the line HttpResponseMessage response = await httpClient.PutAsync(output, streamContent);, execution immediately jumps to the line after t.Join(); with no errors or exceptions.

What can be done?

Regards.

Upvotes: 0

Views: 4804

Answers (1)

Attilio Gelosa
Attilio Gelosa

Reputation: 561

Thank you to Yenhen Cherkes for the suggestion. Following the code that works for me.

The method is very simple:

private static async Task UploadAsync(Uri tempFileName, Uri output)
{
    try
    {
        using (FileStream fileStream = File.OpenRead(tempFileName.LocalPath))
        {
            HttpClient httpClient = new HttpClient();
            StreamContent streamContent = new(fileStream);

            await httpClient.PutAsync(output, streamContent);
        }
    }
    catch (Exception e)
    {
        throw e;
    }
}

To call this method use:

output = GetPresignedUrl(amazonS3, awsPresignedUrlOptions);
await UploadAsync(tempFileName, output);

where output is the pre-signed URI and tempFileName is the URI to the local resource.

Upvotes: 0

Related Questions