MyApp

Getting Started

IntroductionInstallationPull Updates
Architecture

Setup

IDEAI AgentsMCP ServersEnvironment Variables

Workflow

Git WorkflowBuild & DeployTroubleshooting

Authentication

OverviewSetup & ConfigurationUsage & IntegrationTroubleshooting

Payments

OverviewSetup & ConfigurationUsage & IntegrationTroubleshooting

Supabase

OverviewSetup & ConfigurationTroubleshooting

Database

Database SetupPrisma ORMUsage & IntegrationMigrationsTroubleshooting

Storage

OverviewSetup & ConfigurationUsage & IntegrationTroubleshooting

Emails

OverviewSetup and ConfigurationUsage and IntegrationTroubleshooting

SEO

OverviewConfiguration & Best PracticesCustomization & Optimization

UI

OverviewSetup and ConfigurationThemingTroubleshooting
MyApp

Usage & Integration

Learn how to upload and retrieve files from AWS S3.

This page shows practical examples of using AWS S3 in Plainform for file uploads and retrieval.

S3 Client Import

Import the pre-configured S3 client:

Import S3 client
import { s3 } from '@/lib/amazon/s3';
import { env } from '@/env';

Listing Objects

Retrieve files from a specific folder (prefix):

app/api/stripe/orders/route.ts
import { ListObjectsV2Command } from '@aws-sdk/client-s3';
import { s3 } from '@/lib/amazon/s3';
import { env } from '@/env';

export async function GET() {
  const listObjects = await s3.send(
    new ListObjectsV2Command({
      Bucket: env.AWS_S3_BUCKET,
      Prefix: 'mockupUsers/',
      MaxKeys: 5,
    })
  );

  const files = listObjects.Contents?.map(obj => ({
    key: obj.Key,
    size: obj.Size,
    lastModified: obj.LastModified,
    url: `${env.AWS_S3_ENDPOINT}/${obj.Key}`
  }));

  return NextResponse.json({ files });
}

Use case: Plainform uses this to retrieve placeholder user avatars for the orders page.

Uploading Files

Upload a file to S3 and get its URL:

lib/amazon/uploadFile.ts
import { PutObjectCommand } from '@aws-sdk/client-s3';
import { s3 } from '@/lib/amazon/s3';
import { env } from '@/env';

export async function uploadFile(file: File, folder: string) {
  const key = `${folder}/${Date.now()}-${file.name}`;
  
  const command = new PutObjectCommand({
    Bucket: env.AWS_S3_BUCKET,
    Key: key,
    Body: Buffer.from(await file.arrayBuffer()),
    ContentType: file.type,
  });

  await s3.send(command);

  const url = `${env.AWS_S3_ENDPOINT}/${key}`;
  return { key, url };
}

Use in an API route:

app/api/upload/route.ts
import { uploadFile } from '@/lib/amazon/uploadFile';
import { NextResponse } from 'next/server';

export async function POST(req: Request) {
  const formData = await req.formData();
  const file = formData.get('file') as File;

  if (!file) {
    return NextResponse.json({ error: 'No file provided' }, { status: 400 });
  }

  const { key, url } = await uploadFile(file, 'uploads');

  return NextResponse.json({ key, url });
}

Getting Object URLs

Generate public URLs for S3 objects:

Generate URL
import { env } from '@/env';

function getS3Url(key: string): string {
  return `${env.AWS_S3_ENDPOINT}/${key}`;
}

// Example
const avatarUrl = getS3Url('mockupUsers/avatar1.png');
// Returns: https://your-bucket.s3.region.amazonaws.com/mockupUsers/avatar1.png

Signed URLs (Temporary Access)

Generate temporary URLs for private files:

lib/amazon/getSignedUrl.ts
import { GetObjectCommand } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
import { s3 } from '@/lib/amazon/s3';
import { env } from '@/env';

export async function getSignedUrl(key: string, expiresIn: number = 3600) {
  const command = new GetObjectCommand({
    Bucket: env.AWS_S3_BUCKET,
    Key: key,
  });

  const url = await getSignedUrl(s3, command, { expiresIn });
  return url;
}

Use case: Generate temporary download links for private files that expire after a set time.

Deleting Files

Remove files from S3:

lib/amazon/deleteFile.ts
import { DeleteObjectCommand } from '@aws-sdk/client-s3';
import { s3 } from '@/lib/amazon/s3';
import { env } from '@/env';

export async function deleteFile(key: string) {
  const command = new DeleteObjectCommand({
    Bucket: env.AWS_S3_BUCKET,
    Key: key,
  });

  await s3.send(command);
}

Using S3 URLs in Components

Fetch and display S3 files in your components:

app/gallery/page.tsx
import { s3 } from '@/lib/amazon/s3';
import { ListObjectsV2Command } from '@aws-sdk/client-s3';
import { env } from '@/env';
import Image from 'next/image';

export default async function GalleryPage() {
  // List images from S3
  const listObjects = await s3.send(
    new ListObjectsV2Command({
      Bucket: env.AWS_S3_BUCKET,
      Prefix: 'gallery/',
    })
  );

  const images = listObjects.Contents?.map(obj => ({
    key: obj.Key!,
    url: `${env.AWS_S3_ENDPOINT}/${obj.Key}`
  })) || [];

  return (
    <div className="grid grid-cols-3 gap-4">
      {images.map(image => (
        <Image
          key={image.key}
          src={image.url}
          alt={image.key}
          width={300}
          height={300}
          className="rounded-lg"
        />
      ))}
    </div>
  );
}

Email Templates

Reference S3 assets in email templates:

emails/OrderStatusTemplate.tsx
import { Img } from '@react-email/components';

export function OrderStatusTemplate() {
  return (
    <Img
      src="https://plainform.s3.eu-central-1.amazonaws.com/fullLogo.png"
      alt="Plainform Logo"
      width={150}
    />
  );
}

Plainform stores email assets (logos, images) on S3 for reliable delivery across email clients.

File Upload Form Example

Complete example with form handling:

components/FileUploadForm.tsx
'use client';

import { useState } from 'react';

export function FileUploadForm() {
  const [file, setFile] = useState<File | null>(null);
  const [uploading, setUploading] = useState(false);
  const [url, setUrl] = useState<string>('');

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!file) return;

    setUploading(true);

    const formData = new FormData();
    formData.append('file', file);

    const response = await fetch('/api/upload', {
      method: 'POST',
      body: formData,
    });

    const data = await response.json();
    setUrl(data.url);
    setUploading(false);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="file"
        onChange={(e) => setFile(e.target.files?.[0] || null)}
      />
      <button type="submit" disabled={!file || uploading}>
        {uploading ? 'Uploading...' : 'Upload'}
      </button>
      {url && <p>Uploaded: {url}</p>}
    </form>
  );
}

Next Steps

  • Troubleshooting - Resolve common S3 issues
  • AWS S3 SDK Documentation - Complete SDK reference

How is this guide ?

Last updated on

Setup & Configuration

Configure AWS S3 credentials and create your storage bucket.

Troubleshooting

Common AWS S3 issues and how to resolve them.

On this page

S3 Client Import
Listing Objects
Uploading Files
Getting Object URLs
Signed URLs (Temporary Access)
Deleting Files
Using S3 URLs in Components
Email Templates
File Upload Form Example
Next Steps