1. Introduction
  2. Creating the basic form
  3. Integrating with AWS
  4. Integrating with S3
  5. Adding background tasks
  6. Sending emails and creating download links

Introduction

In the last tutorial, you learned how to integrate your application with different AWS services and deploy it to Elastic Beanstalk. Now, it’s time to take care of some of the core functionality: uploading and downloading files from S3.

Creating the bucket

In order to work with files in S3, we must first create a bucket – in a way, you can think of them as directories. You can use buckets for multiple purposes, such as hosting static websites, but we are only going to use a bucket for storing our files.

To create a bucket, search for the S3 service in the AWS Management Console, click the Create bucket button and name it ‘transferzor-files’; leave all other options as default:

Creating the S3 upload/download service

Now that we have a bucket, we can create a service class in our application that will be used to upload and download files from this bucket. First of all, let’s install the ‘AWSSDK.S3’ NuGet package:

And the ‘AWSSDK.Extensions.NETCore.Setup’, for injecting AWS services into our application:

Before creating any service class, let’s create a model that will represent a file. In the Models folder, create a new class called TransferFile; it will simply contain the file name and a byte array:

Next, let’s create an interface in the Services folder called IAwsS3FileManager. This contains thrww methods – one for uploading a file, one for downloading a file, and another one for deleting a file:

Next, create a class called AwsS3FileManager that implements the interface. We will take an IAmazonS3 instance as parameter, which will be used to interact with our S3 bucket. We will also store the bucket name as a field; it’s debatable whether this is a good practice or not, but this is almost static data, so we will not encounter problems unless we change the bucket we are using:

To inject the service, open the Startup.cs file and add the two lines after the DB context is injected; the first one takes care of the IAmazonS3 injection, while the second one handles our own service:

Let’s take a look at the UploadFileAsync method. It takes two parameters: the file name and a Stream object that represents the content of the file – this will come from the InputFile component we created in a previous tutorial. It begins by copying the stream constructing a new file name based on the current time, in order to avoid duplicate names in the bucket. Then, in creates the TransferUtilityUploadRequest object, including the content type, input stream, file and bucket names. Finally, it sends the upload request and returns the new file name – which will be needed for saving in the database:

Next, let’s analyze the DownloadFileAsync method. This one only takes the file name as parameter – which will be the full file name, including the timestamp, and returns a TransferFile object. It firstly creates a GetObjectRequest object containing the bucket and file names, and then tries to retrieve the object (the file, in this case) from the bucket, using the IAmazonS3 instance. If it succeeds, it returns the TransferFile object with the name and content of the file.

Finally, let’s look at the DeleteFileAsync method. This also takes a single parameter, the file name, but does not return any value. It creates the DeleteObjectRequest object, sends the request through the S3 client, and throws an exception if anything goes wrong – which will be useful in later tutorials:

Now that the S3 service is completed, we can think about how this should be integrated into our application. If you remember, there’s a table in the database, FileStorageData, where we want to store our file names from S3 after they’ve been saved. To do this, we will create another service that performs both the database operations, as well as calling the methods from the S3 service. Begin by creating an interface called IFileHandler in the Services folder:

Then, let’s create the implementation of this interface in a class called FileHandler. We will inject the database context, as well as the S3 service:

Firstly, let’s look at the UploadFileAsync method. It takes a FileSendData object as parameter – which will come from the Razor component. It adds the data from that object to the database, then uploads the file to S3, and finally creates and adds the FileStorageData object to the database:

Next, let’s analyze the DownloadFileAsync method. This one takes the file name as parameter (again, this will be the complete file name, including the timestamp) and returns a TransferFile object. First, it checks if there is an entry in the database corresponding to the file name (and returns an empty object if there isn’t one). Next, it downloads the file from S3 and, prior to returning it, deletes the entries from the database and the file from S3:

In the Startup class, inject the FileHandler after the other two classes:

Uploading the files from the form

Now that we have our services in place, it’s time to call the from the front-end. In the SendFileForm component, let’s make the following changes:

  • Inject an IFileHandler instance, instead of the DB context:
  • In the HandleValidSubmit method, use the new service instead of the database:

And that’s it, finally! If you run your application and upload a file, you should be able to see it in your S3 bucket:

No responses yet

Leave a Reply

Your email address will not be published. Required fields are marked *

Learn ASP.NET Core!
Subscribe!
Get the latest articles on .NET and cloud!