Skip to main content

File Uploads

Add S3 file uploads to your SST app.


To allow your users to upload files to your app you'll need to:

  1. Create an S3 bucket
  2. Bind your frontend to the bucket
  3. Generate a presigned URL for the upload
  4. Upload the file by making a request to the URL

Let's look at this in detail!

Get started

Start by creating a new SST + Next.js app by running the following command in your terminal. We are using Next.js for this example but you can use your favorite frontend.

npx create-sst@latest --template standard/nextjs

Add an S3 bucket

Next, add an S3 bucket to your stacks. This will allow you to store the uploaded files.

const bucket = new Bucket(stack, "public");

Make sure to import the Bucket construct.

- import { StackContext, NextjsSite } from "sst/constructs";
+ import { Bucket, StackContext, NextjsSite } from "sst/constructs";

Bind the bucket

After adding the bucket, bind your Next.js app to it.

const site = new NextjsSite(stack, "site", {
path: "packages/web",
+ bind: [bucket],

This allows Next.js app to access our S3 bucket.

Generate a presigned URL

When a user uploads a file, we want to generate a presigned URL that allows them to upload the file directly to S3. We will do this using the AWS SDK.

export async function getServerSideProps() {
const command = new PutObjectCommand({
ACL: "public-read",
Key: crypto.randomUUID(),
Bucket: Bucket.public.bucketName,
const url = await getSignedUrl(new S3Client({}), command);

return { props: { url } };

The above generates a presigned URL that allows public-read access to the uploaded files. You can change the ACL to private or authenticated-read if you prefer.

Add the imports

Import the required packages.

import crypto from "crypto";
import { Bucket } from "sst/node/bucket";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";

Make sure to install them as well.

npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner

Create an upload form

Finally, we can create a form that allows users to upload a file:

export default function Home({ url }: { url: string }) {
return (
onSubmit={async (e) => {

const file = ( as HTMLFormElement).file.files?.[0]!;

const image = await fetch(url, {
body: file,
method: "PUT",
headers: {
"Content-Type": file.type,
"Content-Disposition": `attachment; filename="${}"`,

window.location.href = image.url.split("?")[0];
<input name="file" type="file" accept="image/png, image/jpeg" />
<button type="submit">Upload</button>

This form uploads the file directly to S3 and redirects to the file's URL.

That's it! You now know how to add file uploads with S3 to your SST app.