Working with S3 and Cloud Storage in TypeScript
Modern web applications increasingly use cloud object storage for storing files, images, backups, and static content. Amazon S3 (Simple Storage Service) is the de facto standard in this area, and its API is supported by most cloud providers and local solutions such as MinIO, DigitalOcean Spaces, or Yandex Object Storage. In this article, we will look at how to work with S3-compatible storage in TypeScript using the official AWS SDK and alternative libraries.
Choosing a Library for Working with S3 in TypeScript
There are several popular solutions for interacting with S3 from TypeScript:
- @aws-sdk/client-s3 — the official SDK from Amazon, written in TypeScript, modular and modern.
- aws-sdk — the classic version of the SDK (v2), which is still supported, but migration to v3 is recommended.
- minio — a client library for MinIO and any S3-compatible storage, simple and lightweight.
- s3-client — a minimalistic wrapper over the fetch API for working with S3.
We will focus on @aws-sdk/client-s3 as the most relevant and powerful tool, and also show examples with minio for cases where a lightweight alternative is needed.
Installation and Setup
Install the necessary packages via npm:
npm install @aws-sdk/client-s3 @aws-sdk/lib-storagenpm install --save-dev @types/node typescriptFor working with MinIO:
npm install minioNow let's create a basic S3 client. Make sure you have environment variables or a configuration with access keys.
Example 1: Initializing an S3 Client
import { S3Client } from "@aws-sdk/client-s3";
const s3Client = new S3Client({ region: process.env.AWS_REGION || "us-east-1", credentials: { accessKeyId: process.env.AWS_ACCESS_KEY_ID!, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!, }, // For MinIO or local S3, specify the endpoint: // endpoint: "http://localhost:9000", // forcePathStyle: true,});
export default s3Client;Note the forcePathStyle parameter — it is required for MinIO and some other non-AWS storage.
Example 2: Uploading a File to S3
To upload a file, use the PutObjectCommand:
import { PutObjectCommand } from "@aws-sdk/client-s3";import s3Client from "./s3Client";
async function uploadFile(bucket: string, key: string, body: Buffer | string) { const command = new PutObjectCommand({ Bucket: bucket, Key: key, Body: body, ContentType: "application/octet-stream", });
try { const response = await s3Client.send(command); console.log("File uploaded:", response.$metadata.httpStatusCode); return response; } catch (error) { console.error("Upload error:", error); throw error; }}
// Usage:await uploadFile("my-bucket", "uploads/image.png", bufferFromFile);For streaming large file uploads, use @aws-sdk/lib-storage:
import { Upload } from "@aws-sdk/lib-storage";import { Readable } from "stream";
const upload = new Upload({ client: s3Client, params: { Bucket: "my-bucket", Key: "large-file.zip", Body: Readable.from(fileStream), },});
upload.on("httpUploadProgress", (progress) => { console.log(`Uploaded: ${progress.loaded} of ${progress.total}`);});
await upload.done();Example 3: Downloading a File
To retrieve an object from storage, use GetObjectCommand:
Also in library
Recommendations