DEV Community

Cover image for .Net 6 WebAPI - Upload files to AWS S3 - Step by Step
Mohamad Lawand
Mohamad Lawand

Posted on

.Net 6 WebAPI - Upload files to AWS S3 - Step by Step

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

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

dotnet new webapi -n AutoUpload
Enter fullscreen mode Exit fullscreen mode

Create the classlib which is responsible for S3 communication

dotnet new classlib -n AwsS3
Enter fullscreen mode Exit fullscreen mode

Add reference between the webapi and the classlib

dotnet add AutoUpload/AutoUpload.csproj reference AwsS3/AwsS3.csproj
Enter fullscreen mode Exit fullscreen mode

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

dotnet add package AWSSDK.S3 
Enter fullscreen mode Exit fullscreen mode

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

public class S3Object
{
    public string Name { get; set; } = null!;
    public MemoryStream InputStream { get; set; } = null!;
        public string BucketName { get; set; } = null!;
}
Enter fullscreen mode Exit fullscreen mode

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

public class S3ResponseDto
{
    public int StatusCode { get; set; }
    public string Message { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

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

public class AwsCredentials
{
    public string AccessKey { get; set; } = "";
    public string SecretKey { get; set; } = "";
}
Enter fullscreen mode Exit fullscreen mode

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

public class Constants
{
    public static string AccessKey = "AccessKey";
    public static string SecretKey = "SecretKey";
}
Enter fullscreen mode Exit fullscreen mode

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

using AwsS3.Models;
using AwsS3.Models.DTO;

namespace AwsS3.Services;

public interface IStorageService
{
    Task<S3ResponseDto> UploadFileAsync(S3Object obj, AwsCredentials awsCredentialsValues);
}
Enter fullscreen mode Exit fullscreen mode

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

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;
    }
}
Enter fullscreen mode Exit fullscreen mode

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

"AwsConfiguration": {
    "AWSAccessKey": "ACCESSKEYID",
    "AWSSecretKey": "SECRETKEY"
  }
Enter fullscreen mode Exit fullscreen mode

Next we need to update our controller

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);

    }
}
Enter fullscreen mode Exit fullscreen mode

Please comment your questions below

Discussion (0)