Skip to content
Learni
View all tutorials
Cloud Computing

How to Use Cloud Storage with AWS S3 in 2026

Lire en français

Introduction

Cloud Storage allows you to store files in a scalable way without managing physical servers. AWS S3 is the most widely used service for this purpose. This tutorial teaches you how to integrate S3 into a Node.js application, from setup to CRUD operations. You'll save time by avoiding common configuration mistakes.

Prerequisites

  • Node.js 20+
  • AWS account with access keys
  • Basic TypeScript knowledge
  • AWS CLI installed (optional)

Project Initialization

terminal
mkdir s3-cloud-storage
cd s3-cloud-storage
npm init -y
npm install @aws-sdk/client-s3 dotenv
npm install --save-dev typescript @types/node ts-node
npx tsc --init

This command creates a TypeScript project and installs the modern AWS S3 v3 SDK along with dotenv for environment variables.

AWS Configuration

src/config.ts
import { S3Client } from '@aws-sdk/client-s3';
import * as dotenv from 'dotenv';

dotenv.config();

export const s3Client = new S3Client({
  region: process.env.AWS_REGION || 'eu-west-3',
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
  },
});

The S3 client is configured once. Always use environment variables for your keys to keep your code secure.

Upload a File

src/upload.ts
import { PutObjectCommand } from '@aws-sdk/client-s3';
import { s3Client } from './config';
import * as fs from 'fs';

async function uploadFile(bucket: string, key: string, filePath: string) {
  const fileContent = fs.readFileSync(filePath);
  const command = new PutObjectCommand({
    Bucket: bucket,
    Key: key,
    Body: fileContent,
    ContentType: 'application/pdf',
  });
  await s3Client.send(command);
  console.log(`Fichier uploadé : ${key}`);
}

uploadFile('mon-bucket-2026', 'documents/rapport.pdf', './rapport.pdf');

PutObjectCommand allows you to upload any file. Always specify the ContentType for correct display in the AWS console.

Download a File

src/download.ts
import { GetObjectCommand } from '@aws-sdk/client-s3';
import { s3Client } from './config';
import * as fs from 'fs';

async function downloadFile(bucket: string, key: string, outputPath: string) {
  const command = new GetObjectCommand({ Bucket: bucket, Key: key });
  const response = await s3Client.send(command);
  const stream = response.Body as NodeJS.ReadableStream;
  const writeStream = fs.createWriteStream(outputPath);
  stream.pipe(writeStream);
  console.log(`Fichier téléchargé : ${outputPath}`);
}

downloadFile('mon-bucket-2026', 'documents/rapport.pdf', './downloaded.pdf');

GetObjectCommand returns a stream. Pipe it to a local file to save the content.

List Objects

src/list.ts
import { ListObjectsV2Command } from '@aws-sdk/client-s3';
import { s3Client } from './config';

async function listFiles(bucket: string, prefix: string = '') {
  const command = new ListObjectsV2Command({ Bucket: bucket, Prefix: prefix });
  const response = await s3Client.send(command);
  response.Contents?.forEach(obj => console.log(obj.Key));
}

listFiles('mon-bucket-2026', 'documents/');

ListObjectsV2Command is the modern method for listing files. The prefix allows filtering by virtual folder.

Delete an Object

src/delete.ts
import { DeleteObjectCommand } from '@aws-sdk/client-s3';
import { s3Client } from './config';

async function deleteFile(bucket: string, key: string) {
  const command = new DeleteObjectCommand({ Bucket: bucket, Key: key });
  await s3Client.send(command);
  console.log(`Fichier supprimé : ${key}`);
}

deleteFile('mon-bucket-2026', 'documents/rapport.pdf');

DeleteObjectCommand permanently deletes an object. Note: there is no recycle bin by default on S3.

Best Practices

  • Always use environment variables for credentials
  • Enable versioning on your buckets in production
  • Use consistent key names with prefixes
  • Limit IAM permissions to the strict minimum
  • Add tags to objects for cost tracking

Common Mistakes to Avoid

  • Forgetting to configure the AWS region (signature error)
  • Hardcoding credentials in the code
  • Not handling network errors with try/catch
  • Ignoring object size limits (5 GB for simple PutObject)

Going Further

Discover our complete cloud training to master AWS, GCP and Azure.