Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

README.md

S3 upload example

An example of uploading images from iOS, Android or web to an AWS S3 bucket using Expo Router and EAS Hosting.

To upload content to S3 securely, we create an API route which will generate a signed URL that allows the client to upload a file to a specific bucket for a fixed duration. This API route is a server-side function which will be deployed to EAS Hosting, meaning it is safe to use sensitive environment variables such as your S3 bucket credentials.

Launch your own

Launch with Expo

s3-full.mp4

Create a new project with this example:

npx create-expo-app --example with-s3

You may use credentials for an existing S3 bucket, or create a new one.

First, make a copy of .env.example in this codebase and rename it to .env.local. This file will be gitignored and should never be checked into source control.

The instructions below explain how to create a new bucket, but to use an existing one, fill in the environment variables in .env.local.

Now let's create an S3 bucket. Log in to your AWS account and create a new bucket. Ensure you uncheck "Block all public access".

Open your bucket and under the "Permissions" tab, under "Bucket policy", edit it and add the following (ensure you replace YOUR-BUCKET-NAME with your bucket name):

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadGetObject",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::YOUR-BUCKET-NAME/*"
    }
  ]
}

Open your .env.local and add your AWS_REGION (e.g. us-east-1) and the AWS_BUCKET_NAME (e.g. my-bucket).

Now we need to create an IAM user that has permission to upload to your S3 buckets.

Log in to your AWS account and create a new IAM user. On your newly created IAM user, click "Create access key". You'll only see these values once: add them to your .env.local under AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.

To support web uploads and to be able to view the uploaded image, you also need to add the CORS policy. In your bucket, open Permissions -> Cross-origin resource sharing (CORS) and add the following:

[
  {
    "AllowedHeaders": ["*"],
    "AllowedMethods": ["GET", "PUT", "POST", "DELETE"],
    "AllowedOrigins": ["*"],
    "ExposeHeaders": []
  }
]

Warning

The above setup for S3 creates a highly permissive policy for testing purposes. For production use, ensure you adjust this accordingly to your project requirements.

Test locally

After completing the above, you should be able to upload images locally on iOS, Android, and Web. The API route is running locally at http://localhost:8081. When you've confirmed it is working as expected, see the next section about deploying your API routes.

Deploy to EAS Hosting

Export the web project:

npx expo export --platform web

Note

If you are looking to implement upload for your iOS and Android projects only, add --no-ssg to your export command. This will create a deployable bundle with only your API routes, without the web UI.

(Optional) Upload the environment variables to EAS environment variables

npx eas-cli env:push --environment production

Note

The environment variables will default to "plain text" visibility on the EAS dashboard. You may change the visibility on the UI, but only use plain text or sensitive (secret environment variables cannot be used in local deployments).

Deploy the project:

npx eas-cli deploy --environment production --prod

Note

The --environment production will use environment variables uploaded earlier. Omitting this flag will use environment variables in your local .env or .env.local. The --prod flag will promote the deployment to production, so it will be accessible under https://your-chosen-name.expo.app.

To test your upload against the deployed API, change the API_URL constant in app/index.tsx to your deployed URL.