multer-s3

Streaming Multer storage engine that uploads files directly to AWS S3 using the official v3 SDK.

Library
npm
v3.0.1
676stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
44/100Fair
Development Activity0
Maintenance20
Community68
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
49/100Fair
Architecture60
Code Quality50
Innovation50
Learning Curve35

multer-s3 is a storage engine for Multer, Express’s popular multipart/form-data middleware, that streams uploaded files straight to an Amazon S3 bucket instead of buffering them to local disk first. It plugs into Multer’s standard storage engine interface, so switching from disk or memory storage to S3 is a matter of swapping the storage option — no changes to route handlers or the rest of the upload pipeline.

Built on AWS SDK v3’s @aws-sdk/lib-storage Upload class, it supports the full range of S3 upload parameters — ACL, cache-control, content-type detection (including SVG sniffing), content-disposition, content-encoding, storage class, and both SSE-S3 and SSE-KMS server-side encryption — each configurable as a static value or a per-file function. It also handles automatic cleanup of failed uploads through Multer’s _removeFile hook.

What You Get

  • A drop-in Multer StorageEngine implementation requiring only an S3 client instance and bucket name to get started
  • Full control over ACL, content-type, cache-control, content-disposition, content-encoding, and storage class per upload
  • Built-in server-side encryption configuration (SSE-S3 or SSE-KMS)
  • Automatic orphaned-object cleanup via S3 delete when a multi-file upload partially fails

Common Use Cases

  • Streaming user-uploaded images or avatars directly to S3
  • Storing user documents and PDFs with encryption and access control
  • Building multi-tenant file storage with per-request bucket/key logic
  • Serving CDN-backed static assets uploaded through a web form

Under The Hood

Architecture The module is a single-file (index.js) factory: module.exports = function (opts) { return new S3Storage(opts) }. The S3Storage constructor validates each option with a typeof switch and assigns a getter function per field (bucket, key, acl, metadata, cacheControl, contentDisposition, contentEncoding, storageClass, serverSideEncryption, sseKmsKeyId), using a shared staticValue closure to normalize plain values into (req, file, cb)-style functions. It implements Multer’s two-method StorageEngine contract: _handleFile gathers all per-file config in parallel via run-parallel, then pipes the file stream into an @aws-sdk/lib-storage Upload; _removeFile issues a DeleteObjectCommand for cleanup. The design is flat and easy to follow but monolithic — every new configurable option means another repeated switch/case block in the constructor.

Tech Stack Targets Node >= 12 with no build step or TypeScript — plain CommonJS throughout. Core dependencies are @aws-sdk/lib-storage (streaming multipart upload) plus a peer dependency on @aws-sdk/client-s3 (the consumer supplies the S3Client), file-type for magic-byte content-type sniffing, html-comment-regex for SVG detection, and run-parallel for callback-style concurrent option resolution. Dev tooling is dated: mocha for tests, standard for lint/style enforcement, and express/form-data/on-finished to drive a full multipart-request test harness.

Code Quality Tests in test/basic.js mock all S3 access via a mock-s3 utility, so the suite runs fully offline; it covers option-validation TypeErrors and a full successful-upload path asserting the resulting file metadata. Error handling is uniformly Node-style callbacks ((err, result)), consistent but pre-async/await. A .travis.yml is present but Travis CI’s free tier has been defunct for years, so continuous integration is effectively stale; there’s no GitHub Actions workflow in the repo. No type definitions ship with the package.

API Design The public surface is a single factory function that mirrors Multer’s own StorageEngine documentation example almost verbatim, so anyone already using Multer has essentially no onboarding cost. Option names track their S3 API counterparts directly (ACL, StorageClass, ServerSideEncryption), which keeps translation friction with AWS docs low, and every option accepts either a static value or a per-file function for dynamic cases. The rough edges are the callback-based (req, file, cb) option signature, which predates promises/async-await, and validation errors that surface as a generic TypeError rather than field-specific messages.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search