AWS S3 Upload
A developer-ready Express component for secure file uploads to AWS S3 using Multer and AWS SDK. Supports single and multiple uploads with public URLs and validation.
Overview
This component provides an Express + AWS S3 integration for handling file uploads efficiently and securely. It supports both single and multiple file uploads using Multer-S3, with full control over file validation, naming, and upload limits. It’s ideal for scalable systems requiring direct S3 uploads, such as profile pictures, documents, or media files.
Installation
What This Does
Installs a complete AWS S3 file upload system using Multer-S3. Includes routes, configuration, and validation logic for secure file handling.
Files & Folders Created
| File / Path | Description |
|---|---|
| /src/config/aws.js | Configures AWS SDK and credentials. |
| /src/services/s3UploadService.js | Handles S3 uploads, filtering, and validation. |
| /src/routes/upload.js | Defines single and multiple upload endpoints. |
| /server.js.example | Demonstrates full Express integration. |
| /.env.example | Example configuration for AWS and file size limits. |
Files to be modified
| File / Path | Description |
|---|---|
| server.js | Adds /api/upload routes. |
| .env | Adds AWS credentials and file restrictions. |
Configuration
# AWS Configuration AWS_ACCESS_KEY_ID=your-aws-access-key-id AWS_SECRET_ACCESS_KEY=your-aws-secret-access-key AWS_REGION=us-east-1 S3_BUCKET_NAME=your-bucket-name # Upload Configuration MAX_FILE_SIZE=5242880 ALLOWED_FILE_TYPES=image/jpeg,image/png,application/pdf
Frontend Integration
Use the following **Next.js example** to upload files directly from your frontend using the provided Express S3 endpoints.
Uploads a single file to AWS S3.
Uploads multiple files (max 5) to AWS S3.
Error response for invalid file type or size.
Example
1// app/components/FileUploader.jsx
2'use client';
3import { useState } from 'react';
4
5export default function FileUploader() {
6 const [file, setFile] = useState(null);
7 const [message, setMessage] = useState('');
8 const [uploadedUrl, setUploadedUrl] = useState('');
9
10 const handleUpload = async () => {
11 if (!file) {
12 setMessage('Please select a file to upload');
13 return;
14 }
15
16 const formData = new FormData();
17 formData.append('file', file);
18
19 setMessage('Uploading...');
20 try {
21 const res = await fetch('/api/upload/single', {
22 method: 'POST',
23 body: formData,
24 });
25 const data = await res.json();
26 if (res.ok) {
27 setUploadedUrl(data.file.url);
28 setMessage('✅ File uploaded successfully');
29 } else {
30 setMessage('❌ ' + (data.error || 'Upload failed'));
31 }
32 } catch (err) {
33 setMessage('❌ Upload error: ' + err.message);
34 }
35 };
36
37 return (
38 <div className="max-w-md mx-auto bg-black/20 border border-white/10 rounded-xl p-6 text-white space-y-4">
39 <h2 className="text-xl font-semibold">Upload to AWS S3</h2>
40
41 <input
42 type="file"
43 onChange={(e) => setFile(e.target.files?.[0])}
44 className="block w-full text-sm text-gray-300 border border-white/10 rounded-md cursor-pointer bg-black/30 file:mr-3 file:py-2 file:px-3 file:rounded-md file:border-0 file:bg-emerald-500 file:text-white hover:file:bg-emerald-600"
45 />
46
47 <button
48 onClick={handleUpload}
49 className="w-full bg-emerald-600 hover:bg-emerald-700 py-2 rounded-md font-semibold transition-colors"
50 >
51 Upload File
52 </button>
53
54 {message && <p className="text-sm text-gray-300">{message}</p>}
55 {uploadedUrl && (
56 <a
57 href={uploadedUrl}
58 target="_blank"
59 rel="noopener noreferrer"
60 className="block text-emerald-400 text-sm underline"
61 >
62 View Uploaded File
63 </a>
64 )}
65 </div>
66 );
67}Usage
1// Example S3 Signed URL (for private file access)
2const s3 = require('./src/config/aws');
3
4const url = s3.getSignedUrl('getObject', {
5 Bucket: process.env.S3_BUCKET_NAME,
6 Key: 'uploads/example.png',
7 Expires: 60, // 1 minute
8});
9
10console.log('Signed URL:', url);