'Network Error' uploading files with Amplify Storage

3 minute read
Content level: Advanced
0

Demonstrates how to configure an S3 bucket to accept multipart uploads using Amplify

Situation

I inherited an application using Amplify/React, which I have never used before. The application accepts an uploaded file, saving it to S3 with Storage.put(), but errors out with 'Network Error' when the file is larger than 5MB. Live debugging in the browser shows a CORS error, then a 403.

Task

Change the application to allow files greater than 5MB to be uploaded.

Actions

I didn't consider the S3 bucket configuration at first. The CORS error should have been a clue for an S3 configuration problem, but I went down a different path initially. I searched through various sources including GitHub issues and Stack Overflow articles, all of which were old and wanted me to try some fairly convoluted workarounds. I knew this problem had to have a simple solution. I couldn't imagine that AWS allowed a persistent Amplify bug preventing files >5MB from being uploaded (we didn't). Then I started digging into the CORS angle. I found a sample CORS configuration in this Amplify Documentation.

[
  {
    "AllowedHeaders": ["*"],
    "AllowedMethods": ["GET", "HEAD", "PUT", "POST", "DELETE"],
    "AllowedOrigins": ["*"],
    "ExposeHeaders": [
      "x-amz-server-side-encryption",
      "x-amz-request-id",
      "x-amz-id-2",
      "ETag",
      "x-amz-meta-foo"
    ],
    "MaxAgeSeconds": 3000
  }
]

Note: The documentation suggests using a specific AllowedOrigin or set of origins to further secure your CORS configuration.

After manually changing my upload bucket's configuration, >5MB uploads were succeeding. I then had to figure out how to get the application to put the correct properties on the bucket during deployment.

This was the original Typescript bucket configuration:

    const commonBucketProps = {
      blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
      autoDeleteObjects: true, // emptying bucket prior to deletion
      removalPolicy,
      cors: [
        {
          allowedMethods: [s3.HttpMethods.GET, s3.HttpMethods.PUT, s3.HttpMethods.POST],
          allowedOrigins: ['*'],
          allowedHeaders: ['*']
        }
      ]
    };

How did I figure out the new configuration? By asking Amazon Q, of course! I prompted Q with How would you write this in Typescript?, then pasted in the JSON example from the documentation. Q responded with this code, which worked correctly when deployed.

const commonBucketProps = {
      blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
      autoDeleteObjects: true, // emptying bucket prior to deletion
      removalPolicy,
      cors: [
        {
          allowedMethods: [s3.HttpMethods.GET, s3.HttpMethods.HEAD, s3.HttpMethods.PUT, s3.HttpMethods.POST, s3.HttpMethods.DELETE],
          allowedOrigins: ['*'],
          allowedHeaders: ['*'],
          exposedHeaders: ['x-amz-server-side-encryption','x-amz-request-id','x-amz-id-2','ETag','x-amz-meta-foo'],
          maxAge:         3000
        }
      ]
    };

It's also important to note that if I had prompted Q with "I get a network error and a CORS error when trying to upload a file larger than 5MB using AWS Amplify. How can I correct it?" right out of the gate, I would have found the correct solution much faster.

Result

We can now upload > 5MB files, and I had fun learning how to work with Amplify.

profile pictureAWS
EXPERT
published 12 days ago1391 views