Get started with 33% off your first certification using code: 33OFFNEW

Uploading Files Directly to AWS S3 from an HTML Form Securely

5 min read
Published on 28th March 2023

When building a web application, you may need to allow users to upload files, such as images, videos, or documents. One common approach is to store these files on a cloud storage service like Amazon Web Services (AWS) S3. Uploading files directly from an HTML form to S3 can improve performance and save bandwidth.

Another use-case example for this approach is when you are working in a full immutable architecture, where uploading to your web server isn't reliable. An example of this is when your application is running serverless, so the server you upload to will be destroyed before the file has chance to be uploaded. If you're interested in running serverless infrastructure, especially with PHP, check out our article on An Introduction to Serverless with PHP.

In this article, we'll show you how to securely upload files directly to an S3 bucket from an HTML form, while ensuring the process is safe for untrusted users.

Section 1: Preparing the AWS S3 Bucket

First, create an S3 bucket in your AWS account. If you don't already have an AWS account, sign up for one. Once you're logged in, follow these steps:

  1. Navigate to the S3 Management Console.
  2. Click the "Create bucket" button.
  3. Enter a unique name for your bucket and choose a region.
  4. Keep the default settings for the rest of the options and click "Create bucket."

Next, create a new folder in your bucket to store the uploaded files. This will help keep your bucket organised and separate user-uploaded files from other files.

Section 2: Setting Up an Amazon Cognito Identity Pool

To enable untrusted users to upload files securely to your S3 bucket, we'll use Amazon Cognito, an AWS service that provides authentication and authorisation features. We'll create an Identity Pool with an unauthenticated role that grants users limited permissions to upload files to the S3 bucket.

  1. Navigate to the Amazon Cognito Management Console.
  2. Choose "Manage Identity Pools" and click "Create new identity pool."
  3. Give your identity pool a name and check the "Enable access to unauthenticated identities" box.
  4. Click "Create Pool."
  5. On the next screen, expand the "View Details" section and take note of the "Unauthenticated role" ARN.

Now, we'll update the unauthenticated role's policy to grant users permission to upload files to the S3 bucket.

  1. Navigate to the IAM Management Console.
  2. Click "Roles" in the left sidebar and search for the unauthenticated role you noted earlier.
  3. Click the role to view its details and then click "Attach policies."
  4. Click "Create policy" and switch to the "JSON" tab.
  5. Replace the existing policy with the following JSON, making sure to replace <YOUR_BUCKET_NAME> with your S3 bucket name and <YOUR_UPLOADS_FOLDER> with the folder you created in the bucket:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::<YOUR_BUCKET_NAME>/<YOUR_UPLOADS_FOLDER>/*"
        }
    ]
}
  1. Click "Review policy" and give the policy a name. Then, click "Create policy."
  2. Return to the role's "Attach policies" page, search for the new policy you just created, and click "Attach policy."

Your Amazon Cognito Identity Pool is now set up with the appropriate permissions for untrusted users to upload files to your S3 bucket securely.

Section 3: Creating the HTML Form and JavaScript Code

Create an HTML file with the following form to allow users to select a file for uploading:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>File Upload to S3</title>
</head>
<body>
    <form id="upload-form">
        <input type="file" id="file-input">
        <button type="submit">Upload File</button>
    </form>
    <script src="https://sdk.amazonaws.com/js/aws-sdk-2.813.0.min.js"></script>
    <script src="app.js"></script>
</body>
</html>

Note that you might need to update the AWS JS SDK to the latest version.

Next, create a JavaScript file named app.js and add the following code, making sure to replace <YOUR_REGION> with your AWS region and <YOUR_IDENTITY_POOL_ID> with the Identity Pool ID from Amazon Cognito:

// Configure the AWS SDK
AWS.config.region = '<YOUR_REGION>';
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
    IdentityPoolId: '<YOUR_IDENTITY_POOL_ID>'
});

// Create an S3 client
const s3 = new AWS.S3();

document.getElementById('upload-form').addEventListener('submit', (event) => {
    event.preventDefault();

    const fileInput = document.getElementById('file-input');
    const file = fileInput.files[0];
    if (!file) {
        alert('Please select a file to upload.');
        return;
    }

    const key = `<YOUR_UPLOADS_FOLDER>/${file.name}`;
    const params = {
        Bucket: '<YOUR_BUCKET_NAME>',
        Key: key,
        Body: file
    };

    s3.putObject(params, (err, data) => {
        if (err) {
            console.error('Error uploading file:', err);
            alert('An error occurred while uploading the file.');
        } else {
            console.log('File uploaded successfully:', data);
            alert('File uploaded successfully!');
        }
    });
});

This code configures the AWS SDK with the Cognito Identity Pool credentials and sets up an S3 client. It then listens for the form submission, and when the form is submitted, it uploads the selected file to the specified S3 bucket and folder.

Section 4: Testing the File Upload

To test the file upload functionality, open the HTML file in your web browser, select a file using the file input, and click the "Upload File" button. If the upload is successful, you should see an alert saying "File uploaded successfully!" and the file should appear in your S3 bucket's folder.

Conclusion

In this article, we've shown you how to securely upload files directly to an AWS S3 bucket from an HTML form, making it safe for untrusted users. We've set up an S3 bucket, created an Amazon Cognito Identity Pool to grant limited permissions, and used the AWS SDK to upload files from a web form.

By following this approach, you can improve performance, save bandwidth, and ensure the security of your web application when handling file uploads from untrusted users. Keep in mind that you may also want to implement additional security measures, such as validating file types and sizes, and generating unique file names to avoid overwriting existing files.