Introduction#
GitHub this note shows how to handle uploading files to S3 in a next application.
- Setup project with aws-amplify lib
- Handle upload using Amplify Storage
- Handle upload using S3 Client
- RevalidatePath
Setup Project#
Let create a new nextjs project and add amplify
npx create-next-app@latest
Then add amplify
npm install aws-amplify
We have to create a configuration file named config.ts
export const config = {aws_cognito_region: process.env.AWS_COGNITO_REGION,aws_user_pools_id: process.env.AWS_USER_POOLS_ID,aws_user_pools_web_client_id: process.env.AWS_USER_POOLS_WEB_CLIENT_ID,aws_cognito_identity_pool_id: process.env.AWS_COGNITO_IDENTITY_POOL_ID,aws_user_files_s3_bucket_region: process.env.S3_REGION,aws_user_files_s3_bucket: process.env.BUCKET,};
Upload Form#
Let create a upload form and a server function to handle the form
import { amplifyHandleUpload, getImages } from "./action";const Upload = async () => {const images = await getImages();return (<div className="min-h-screen dark:bg-slate-800"><div className="max-w-3xl mx-auto pt-10"><formclassName="p-5 dark:bg-slate-600 shadow-lg rounded-sm"action={amplifyHandleUpload}><div><inputid="upload"type="file"name="upload"className="text-sm rounded-sm w-full p-2.5 cursor-pointer dark:bg-white bg-slate-100"></input></div><button className="bg-orange-400 px-10 py-3 rounded-sm mt-5">Upload</button></form><div className="grid grid-cols-1 gap-5 pt-10">{images.map((image, id) => (<div key={id}><img src={image} alt={"test"}></img></div>))}</div></div></div>);};export default Upload;
To handle uploading file to s3 we can use Amplify Storage or S3 Client. Let use Amplify Storage
"use server";import { Amplify, Storage } from "aws-amplify";import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";import { fromCognitoIdentityPool } from "@aws-sdk/credential-providers";import { config, imageNames } from "../config";import { revalidatePath } from "next/cache";// amplify handle uploading filetry {Amplify.configure(config);console.log("storage configured OK");} catch (error) {console.log(error);}export const amplifyHandleUpload = async (data: FormData) => {const file = data.get("upload") as File;try {const repsonse = await Storage.put(`${file.name}`, file);console.log(repsonse);} catch (error) {console.log(error);}// redirect("/");revalidatePath("/upload");};
Finally add revalidate path
// get signed url imagesexport const getImages = async () => {"use server";let images: string[] = [];for (var name of imageNames) {try {let response = await Storage.get(name, {validateObjectExistence: true,});images.push(response);console.log(response);} catch (error) {console.log(error);}}return images;};
S3 Client#
Alternatively, we can use s3 client to handle uploading files to s3
// s3 client hanlde uploading fileconst s3Client = new S3Client({region: process.env.S3_REGION,credentials: fromCognitoIdentityPool({clientConfig: { region: process.env.REGION },identityPoolId: process.env.IDENTITY_POOL_ID as string,}),});export const s3ClientHandleUpload = async (data: FormData) => {const file = data.get("upload") as File;try {const bytes = await file.arrayBuffer();const response = await s3Client.send(new PutObjectCommand({Bucket: process.env.BUCKET,Key: `next-amplify-s3/${file.name}`,Body: Buffer.from(bytes),}));} catch (error) {console.log(error);}};