Skip to content
⚠️ Open SaaS is now running on Wasp v0.13! If you're running an older version of Open SaaS, please follow the migration instructions here ⚠️

File Uploading

This guide will show you how to set up file uploading in your SaaS app.

There are two options we recommend:

  1. Using AWS S3 with presigned URLS for secure file storage
  2. Using Multer middleware to upload files to your own server

We recommend using AWS S3 as it’s a scalable, secure option, that can handle a large amount of storage.

If you’re just looking to upload small files and don’t expect your app to grow to a large scale, you can use Multer to upload files to your app’s server.

Using AWS S3

How presigned URLs work

Presigned URLs are URLs that have been signed with your AWS credentials and can be used to upload files to your S3 bucket. They are time-limited and can be generated on the server and sent to the client to upload files directly to S3.

The process of generating a presigned URL is as follows:

  1. The client sends a request to the server to upload a file
  2. The server generates a presigned URL using its AWS credentials
  3. The server sends the presigned URL to the client
  4. The client uses the presigned URL to upload the file directly to S3 before the URL expires

We use this method to upload files to S3 because it is more secure than uploading files directly from the client to S3. It also allows us to keep our AWS credentials private and not expose them to the client.

To use presigned URLs, we’ll need to set up an S3 bucket and get our AWS credentials.

Create an AWS Account

Before you begin, you’ll need to create an AWS account. AWS accounts are free to create and are split up into:

  1. Root account
  2. IAM users

You’ll need to first create a root account, and then an IAM user for your SaaS app before you can start uploading files to S3.

To do so, follow the steps in this external guide: Creating IAM users and S3 buckets in AWS

Create an AWS S3 Bucket

Once you are logged in with your IAM user, you’ll need to create an S3 bucket to store your files.

  1. Navigate to the S3 service in the AWS console find s3
  2. Click on the Create bucket button create bucket
  3. Fill in the bucket name and region
  4. Leave all the settings as default and click Create bucket bucket settings

Change the CORS settings

Now we need to change some permissions on the bucket to allow for file uploads from your app.

  1. Click on the bucket you just created new bucket
  2. Click on the Permissions tab permissions
  3. Scroll down to the Cross-origin resource sharing (CORS) section and click Edit cors
  4. Paste the following CORS configuration and click Save changes:
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"PUT",
"GET"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": []
}
]

Get your AWS S3 credentials

Now that you have your S3 bucket set up, you’ll need to get your S3 credentials to use in your app.

  1. Click on your username in the top right corner of the AWS console and select Security Credentials security credentials
  2. Scroll down to the Access keys section
  3. Click on Create Access Key
  4. Select the Application running on an AWS service option and create the access key access key
  5. Copy the Access key ID and Secret access key and paste them in your src/app/.env.server file:
Terminal window
AWS_S3_IAM_ACCESS_KEY=ACK...
AWS_S3_IAM_SECRET_KEY=t+33a...
AWS_S3_FILES_BUCKET=your-bucket-name
AWS_S3_REGION=your-region // (e.g. us-west-2)

Using and Customizing File Uploads with S3 in your App

With your S3 bucket set up and your AWS credentials in place, you can now start uploading files in your app using presigned URLs by navigating to localhost:3000/file-upload and uploading a file.

To begin customizing file uploads, is important to know where everything lives in your app. Here’s a quick overview:

  • main.wasp:
    • The File entity can be found here. Here you can modify the fields to suit your needs:
      entity File {=psl
      id String @id @default(uuid())
      name String
      type String
      key String
      uploadUrl String
      user User @relation(fields: [userId], references: [id])
      userId Int
      createdAt DateTime @default(now())
      psl=}
  • src/server/actions.ts:
    • The createFile action lives here and calls the getUploadFileSignedURLFromS3 within it using your AWS credentials before passing it to the client. This function stores the files in the S3 bucket within folders named after the user’s ID, so that each user’s files are stored separately.
  • src/server/queries.ts:
    • The getAllFilesByUser fetches all File information uploaded by the user. Note that the files do not exist in the app database, but rather the file data, name its key, which is used to fetch the file from S3
    • The getDownloadFileSignedURL query fetches the presigned URL for a file to be downloaded from S3 using the file’s key stored in the app’s database
  • src/client/app/FileUploadPage.tsx:
    • The FileUploadPage component is where the file upload form lives. It also allows you to download the file from S3 by calling the getDownloadFileSignedURL based on that files key in the app DB.

Using Multer to upload files to your server

If you’re looking to upload files to the app server, you can use the Multer middleware to handle file uploads. This will allow you to store files on your server and is a good option if you need a quick and dirty, free solution for simple file uploads.

Below are GitHub Gists that show you how to set up file uploads using Multer in your app:

Wasp version 0.12 & higher