JAVASCRIPT
Secure File Upload to Cloud Storage via Pre-Signed URLs
Implement secure file uploads directly from the client to cloud storage (e.g., S3) by first generating and using a pre-signed URL from your backend.
// --- Node.js Backend Snippet (Example using AWS SDK for S3) ---
const AWS = require('aws-sdk');
const express = require('express');
const app = express();
const port = 3001;
// Configure AWS S3 (ensure AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION are set as env vars)
const s3 = new AWS.S3({ signatureVersion: 'v4' });
const BUCKET_NAME = 'your-unique-s3-bucket-name'; // Replace with your S3 bucket name
app.get('/generate-upload-url', (req, res) => {
const filename = req.query.filename;
const filetype = req.query.filetype;
if (!filename || !filetype) {
return res.status(400).send('Filename and filetype are required.');
}
const s3Params = {
Bucket: BUCKET_NAME,
Key: `uploads/${Date.now()}-${filename}`, // Path in S3
Expires: 60, // URL expires in 60 seconds
ContentType: filetype,
ACL: 'public-read' // Or private, depending on your use case
};
s3.getSignedUrl('putObject', s3Params, (err, url) => {
if (err) {
console.error('Error generating S3 pre-signed URL:', err);
return res.status(500).send('Error generating upload URL.');
}
res.send({ uploadUrl: url, fileKey: s3Params.Key });
});
});
app.listen(port, () => {
console.log(`Backend for pre-signed URLs running on http://localhost:${port}`);
});
// --- Frontend JavaScript Snippet (React example, but transferable) ---
// <input type="file" id="fileInput" />
// <button onclick="uploadFile()">Upload</button>
async function uploadFile() {
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];
if (!file) {
alert('Please select a file first.');
return;
}
try {
// 1. Get a pre-signed URL from your backend
const response = await fetch(`http://localhost:3001/generate-upload-url?filename=${file.name}&filetype=${file.type}`);
if (!response.ok) {
throw new Error('Failed to get pre-signed URL.');
}
const { uploadUrl, fileKey } = await response.json();
// 2. Upload the file directly to S3 using the pre-signed URL
const uploadResponse = await fetch(uploadUrl, {
method: 'PUT',
headers: {
'Content-Type': file.type,
},
body: file,
});
if (!uploadResponse.ok) {
throw new Error('Failed to upload file to S3.');
}
console.log('File uploaded successfully to S3!', fileKey);
alert('File uploaded successfully!');
// You might want to send fileKey back to your backend to record the upload
} catch (error) {
console.error('Upload error:', error);
alert(`Upload failed: ${error.message}`);
}
}
How it works: This solution demonstrates a secure and scalable way to upload files directly from a client-side application to cloud storage like AWS S3, bypassing your backend server for the heavy lifting. The frontend first requests a 'pre-signed URL' from your backend. Your backend, authenticated with the cloud provider, generates a temporary, time-limited URL that grants specific upload permissions to a particular S3 object key. The frontend then uses this URL to directly PUT the file to S3. This pattern offloads server resources, improves performance, and enhances security by preventing client credentials from being exposed and allowing fine-grained access control to uploads.