Amazon S3 (Simple Storage Service) is one of the most reliable ways to store and serve files like images, videos, and documents.
In this tutorial, youβll learn how to upload an image directly from the browser to your S3 bucket using JavaScript, while your .NET Core backend securely generates a pre-signed URL.
π§© What Is a Pre-Signed URL?
A pre-signed URL is a temporary, secure URL generated by AWS SDK that allows you to upload (PUT) or download (GET) files directly from/to S3 without exposing your AWS credentials.
π Official AWS Docs: Pre-Signed URLs
π οΈ Prerequisites
Before starting, make sure you have:
An AWS account with S3 bucket access
An IAM user with AmazonS3FullAccess
or a custom policy that allows:
{"Version": "2012-10-17","Statement": [
{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject"],
"Resource": "arn:aws:s3:::your-bucket-name/*"
}]}
A .NET 6+ Web API project
A JavaScript (HTML) frontend
π§± Step 1. Install AWS SDK in .NET Core
Install AWS SDK via NuGet:
dotnet add package AWSSDK.S3
βοΈ Step 2. Create Pre-Signed URL API in .NET Core
Hereβs a working example controller to generate a pre-signed URL for S3 upload.
using Amazon.S3;
using Amazon.S3.Model;
using Microsoft.AspNetCore.Mvc;
using System;
namespace AwsUploadDemo.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class S3UploadController : ControllerBase
{
private readonly IAmazonS3 _s3Client;
private const string BucketName = "your-bucket-name";
public S3UploadController(IAmazonS3 s3Client)
{
_s3Client = s3Client;
}
[HttpGet("generate-url")]
public IActionResult GeneratePresignedUrl(string fileName)
{
var key = $"uploads/{Guid.NewGuid()}_{fileName}";
var request = new GetPreSignedUrlRequest
{
BucketName = BucketName,
Key = key,
Verb = HttpVerb.PUT,
Expires = DateTime.UtcNow.AddMinutes(10),
ContentType = "image/jpeg"
};
string presignedUrl = _s3Client.GetPreSignedURL(request);
return Ok(new
{
uploadUrl = presignedUrl,
fileUrl = $"https://{BucketName}.s3.amazonaws.com/{key}"
});
}
}
}
β
What this does:
Generates a temporary URL valid for 10 minutes.
Allows HTTP PUT upload directly to S3.
Returns both the upload URL and the final public file URL.
πΌοΈ Step 3. Upload Image Using JavaScript (Frontend)
Create a simple index.html
page with a file input and an upload button.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AWS S3 Upload via Pre-Signed URL</title>
</head>
<body>
<h2>Upload Image to AWS S3</h2>
<input type="file" id="fileInput" accept="image/*" />
<button id="uploadBtn">Upload</button>
<p id="status"></p>
<img id="preview" width="200" style="margin-top:10px;" />
<script>
document.getElementById("uploadBtn").addEventListener("click", async () => {
const fileInput = document.getElementById("fileInput");
const file = fileInput.files[0];
if (!file) return alert("Please select an image!");
// 1οΈβ£ Request Pre-signed URL from .NET API
const response = await fetch(`https://localhost:5001/api/S3Upload/generate-url?fileName=${file.name}`);
const data = await response.json();
// 2οΈβ£ Upload file directly to S3 using PUT
const uploadResponse = await fetch(data.uploadUrl, {
method: "PUT",
headers: {
"Content-Type": file.type
},
body: file
});
if (uploadResponse.ok) {
document.getElementById("status").innerText = "β
Upload Successful!";
document.getElementById("preview").src = data.fileUrl;
} else {
document.getElementById("status").innerText = "β Upload Failed!";
}
});
</script>
</body>
</html>
β
Flow Explanation
User selects an image.
Frontend requests a pre-signed upload URL from the backend.
File is uploaded directly to S3 via PUT request.
Final image URL is shown to the user.
π Step 4. Secure Your S3 Bucket
To make uploaded images publicly accessible, you can use a bucket policy like:
{"Version": "2012-10-17","Statement": [
{
"Sid": "PublicReadForGetBucketObjects",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::your-bucket-name/*"
}]}
Alternatively, you can keep the bucket private and use signed GET URLs for access.
β‘ Bonus Tips
π§ For multiple file uploads, call the same API for each file.
π For secure uploads, validate the user session before generating the pre-signed URL.
βοΈ Use AWS SDK v3 for JavaScript if you need server-side uploads in Node.js.
π References
π AWS SDK for .NET Documentation
π Using Pre-Signed URLs for S3
π AWS IAM Policies Guide
π CORS Configuration for S3
π§Ύ Summary
Step | Description |
---|
1οΈβ£ | Create a .NET API to generate a pre-signed URL |
2οΈβ£ | Configure AWS S3 permissions |
3οΈβ£ | Use JavaScript fetch() to PUT the image directly |
4οΈβ£ | Display uploaded image URL |
With this approach, you offload the heavy lifting to the browser and keep your API secure β a perfect balance between performance and safety.