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.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs