JAVASCRIPT
JavaScript: Direct File Upload to AWS S3 using Pre-signed URLs
Securely upload files directly from the browser to AWS S3 by first obtaining a pre-signed URL from your backend, bypassing server-side file processing.
// Function to initiate a direct file upload to AWS S3 using a pre-signed URL
async function uploadFileToS3(file) {
if (!file) {
console.error('No file selected for upload.');
return;
}
const filename = file.name;
const fileType = file.type;
// Step 1: Request a pre-signed URL from your backend
// Your backend should have logic to generate this URL using AWS SDK
try {
console.log(`Requesting pre-signed URL for ${filename} (${fileType})...`);
const response = await fetch('/api/get-s3-presigned-url', { // Your backend endpoint
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ filename: filename, fileType: fileType }),
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(`Failed to get pre-signed URL: ${response.status} - ${errorData.message || 'Unknown error'}`);
}
const { uploadUrl, fileKey } = await response.json(); // Backend returns the URL and the final S3 key
console.log('Received pre-signed URL. Initiating direct upload to S3...');
// Step 2: Directly upload the file to S3 using the pre-signed URL
// The PUT request must use the exact fileType received by the backend for the URL generation
const uploadResponse = await fetch(uploadUrl, {
method: 'PUT',
headers: {
'Content-Type': fileType, // CRITICAL: Must match the content type used when generating the pre-signed URL
// Do NOT add Authorization headers here, the URL itself is authorized
},
body: file, // Send the raw file object as body
});
if (!uploadResponse.ok) {
throw new Error(`Failed to upload file to S3: ${uploadResponse.status} - ${uploadResponse.statusText}`);
}
console.log('File successfully uploaded to S3!');
const s3FileLocation = uploadUrl.split('?')[0]; // The URL without query parameters is the S3 object URL
console.log('S3 Object URL:', s3FileLocation);
// You can now use fileKey or s3FileLocation in your application
return { success: true, fileKey: fileKey, s3Location: s3FileLocation };
} catch (error) {
console.error('Error during S3 upload process:', error);
alert('File upload failed: ' + error.message);
return { success: false, error: error.message };
}
}
// Example usage:
// Assuming you have an input type="file" element:
// <input type="file" id="fileInput" />
// <button onclick="handleFileUpload()">Upload</button>
/*
async function handleFileUpload() {
const fileInput = document.getElementById('fileInput');
if (fileInput.files.length > 0) {
const selectedFile = fileInput.files[0];
const result = await uploadFileToS3(selectedFile);
if (result.success) {
console.log('Upload complete, S3 location:', result.s3Location);
// Update UI, save S3 location to database, etc.
}
} else {
alert('Please select a file first.');
}
}
*/
// For demonstration, you might simulate a file:
(async () => {
const dummyFile = new File(['Hello S3! This is a test file.'], 'my-test-document.txt', { type: 'text/plain' });
console.log('Simulating file upload...');
// Uncomment the line below to actually run the upload simulation
// await uploadFileToS3(dummyFile);
console.log('To run, uncomment `await uploadFileToS3(dummyFile);` and ensure your backend endpoint `/api/get-s3-presigned-url` is running.');
})();
How it works: This JavaScript snippet facilitates direct file uploads from a web browser to AWS S3, bypassing your backend server for the actual file transfer. This two-step process begins with the client requesting a "pre-signed URL" from your backend. Your backend, using the AWS SDK, generates a temporary, time-limited URL that grants specific permissions (e.g., PUT object) to a particular S3 bucket and object key. Once the client receives this URL, it directly performs an HTTP PUT request to S3 with the file's content. This method enhances performance and reduces server load by offloading large file transfers, while maintaining security as the upload permissions are controlled by the pre-signed URL.