.Net 6 WebAPI - Upload files to AWS S3 - Step by Step
Tags: dotnet, aws, stepbystep, beginners
Published: 2022-06-08 06:34:57

In this article we will explore AWS S3 and see how we can upload files to our S3 buckets from an .NET 6 Web API.

You can watch the full video on YouTube with detail explanation of S3

{% embed https://youtu.be/6lRdUcbRZ0w %}

You can find the link to the source code below
https://github.com/mohamadlawand087/NET6-S3

Now lets get started 

The first thing we need to do is to create our application inside our terminal

```bash
dotnet new webapi -n AutoUpload
```

Create the classlib which is responsible for S3 communication

```bash
dotnet new classlib -n AwsS3
```

Add reference between the webapi and the classlib

```bash
dotnet add AutoUpload/AutoUpload.csproj reference AwsS3/AwsS3.csproj
```

Now we open the solution in VsCode and we delete the auto generated class inside AwsS3

and we add 2 new folders

- Models
- Services

We install S3 nuget package inside the AwsS3 class lib

```bash
dotnet add package AWSSDK.S3 
```

Now inside our Models folder we need to create our S3 Model, let us add a class called S3Object

```csharp
public class S3Object
{
    public string Name { get; set; } = null!;
    public MemoryStream InputStream { get; set; } = null!;
		public string BucketName { get; set; } = null!;
}
```

Now we need to add another class which will represent the data which is being sent back from S3 after the upload, so we will need to create a new class called S3ResponseDto

```csharp
public class S3ResponseDto
{
    public int StatusCode { get; set; }
    public string Message { get; set; }
}
```

Now we need to another class which will be responsible for storing the AWS credentials which we will utilise to communicate with S3 bucket, so we will create a new class called AwsCredentials a

```csharp
public class AwsCredentials
{
    public string AccessKey { get; set; } = "";
    public string SecretKey { get; set; } = "";
}
```

Now we need to add a section so we can get all of the required configuration so inside our AwsS3 classlib we will create a new folder called configurations in the root directory and inside that folder we will create a new class called Constants which represent the config values name

```csharp
public class Constants
{
    public static string AccessKey = "AccessKey";
    public static string SecretKey = "SecretKey";
}
```

Now inside our service folder we will add a new interface call IStorageService

```csharp
using AwsS3.Models;
using AwsS3.Models.DTO;

namespace AwsS3.Services;

public interface IStorageService
{
    Task<S3ResponseDto> UploadFileAsync(S3Object obj, AwsCredentials awsCredentialsValues);
}
```

Now we need to create the service, so we create a new class called StorageService inside the Services folder

```csharp
using AwsS3.Models;
using AwsS3.Models.DTO;
using Amazon.S3;
using Amazon.S3.Transfer;
using AwsS3.Configurations;
using Amazon.Runtime;

namespace AwsS3.Services;

public class StorageService : IStorageService
{
    //private readonly IConfigurationManager _config;

    public StorageService(IConfigurationManager config)
    {
        //_config = config;
    }

    public async Task<S3ResponseDto> UploadFileAsync(S3Object obj, AwsCredentials awsCredentialsValues)
    {
        //var awsCredentialsValues = _config.ReadS3Credentials();

        Console.WriteLine($"Key: {awsCredentialsValues.AccessKey}, Secret: {awsCredentialsValues.SecretKey}");

        var credentials = new BasicAWSCredentials(awsCredentialsValues.AccessKey, awsCredentialsValues.SecretKey);

        var config = new AmazonS3Config() 
        {
            RegionEndpoint = Amazon.RegionEndpoint.EUWest2
        };

        var response = new S3ResponseDto();
        try
        {
            var uploadRequest = new TransferUtilityUploadRequest()
            {
                InputStream = obj.InputStream,
                Key = obj.Name,
                BucketName = obj.BucketName,
                CannedACL = S3CannedACL.NoACL
            };

            // initialise client
            using var client = new AmazonS3Client(credentials, config);

            // initialise the transfer/upload tools
            var transferUtility = new TransferUtility(client);

            // initiate the file upload
            await transferUtility.UploadAsync(uploadRequest);

            response.StatusCode = 201;
            response.Message = $"{obj.Name} has been uploaded sucessfully";
        }
        catch(AmazonS3Exception s3Ex)
        {
            response.StatusCode = (int)s3Ex.StatusCode;
            response.Message = s3Ex.Message;
        }
        catch(Exception ex)
        {
            response.StatusCode = 500;
            response.Message = ex.Message;
        }

        return response;
    }
}
```

Now we need to go to our API and update our appsettings.json

```json
"AwsConfiguration": {
    "AWSAccessKey": "ACCESSKEYID",
    "AWSSecretKey": "SECRETKEY"
  }
```

Next we need to update our controller

```csharp
using AwsS3.Models;
using AwsS3.Services;
using Microsoft.AspNetCore.Mvc;

namespace AutoUpload.Controllers;

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{

    private readonly IStorageService _storageService;
    private readonly IConfiguration _config;
    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(
        ILogger<WeatherForecastController> logger,
        IConfiguration config,
        IStorageService storageService)
    {
        _logger = logger;
        _config = config;
        _storageService = storageService;
    }

    [HttpPost(Name = "UploadFile")]

    public async Task<IActionResult> UploadFile(IFormFile file)
    {
        // Process file
        await using var memoryStream = new MemoryStream();
        await file.CopyToAsync(memoryStream);

        var fileExt = Path.GetExtension(file.FileName);
        var docName = $"{Guid.NewGuid}.{fileExt}";
        // call server

        var s3Obj = new S3Object() {
            BucketName = "live-demo-bucket821",
            InputStream = memoryStream,
            Name = docName
        };

        var cred = new AwsCredentials() {
            AccessKey = _config["AwsConfiguration:AWSAccessKey"],
            SecretKey = _config["AwsConfiguration:AWSSecretKey"]
        };

        var result = await _storageService.UploadFileAsync(s3Obj, cred);
        // 
       return Ok(result);
       
    }
}
```

Please comment your questions below