multer-s3
Streaming Multer storage engine that uploads files directly to AWS S3 using the official v3 SDK.
Repository Health
Technical Analysis
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
StorageEngineimplementation 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.
Used by 5 apps in this directory
Bigcapital
Invoicing Finance
Self-hostable double-entry accounting platform with invoicing, inventory, multi-currency, and real-time financial reporting for small and medium businesses.
Flowise
Developer Tools · Automation · No Code Platforms
Drag-and-drop visual builder for AI agents, RAG pipelines, and multi-agent systems—deploy anywhere in minutes.
HeyForm
Forms Surveys · No Code Platforms
Open-source conversational form builder with AI generation, conditional logic, and 30+ integrations — self-host with full data ownership.
NocoBase
No Code Platforms · Low Code Platforms
Open-source AI + no-code platform that lets coding agents and people collaborate to build business systems fast on proven infrastructure.
OpenSign
Digital Signiture
Self-host a full-featured DocuSign alternative with unlimited e-signatures, multi-signer workflows, and cryptographic PDF signing.