Implement Azure Blob Storage Using Presigned URL in .NET Core and JavaScript


Cloud file storage is now a standard requirement for modern web applications. Whether you are building a social media platform, blogging system, e-commerce site, or enterprise dashboard, users expect fast and secure file uploads.

One of the best ways to securely upload files to Azure Blob Storage is by using Presigned URLs, commonly known in Azure as SAS (Shared Access Signature) URLs.

Instead of uploading files through your server, the backend generates a temporary secure upload URL, and the frontend uploads directly to Azure Blob Storage.

This approach improves:

  • Performance
  • Security
  • Scalability
  • Server resource usage

According to Microsoft Learn Azure SAS Documentation, SAS provides delegated and time-limited access to Azure Storage resources.

What is a Presigned URL (SAS URL)?

A SAS URL is a temporary URL that grants limited access to a blob or container.

The URL contains:

  • Expiration time
  • Allowed operations
  • Resource path
  • Security signature

Example:

https://myaccount.blob.core.windows.net/uploads/image.png?
sv=2024-01-01&
sr=b&
sig=xxxxx

The frontend can use this URL to upload files directly without exposing Azure credentials.

Why Use SAS URLs?

Traditional Upload Flow

Browser → Your Server → Azure Blob Storage

Problems:

  • Large server bandwidth usage
  • Slow uploads
  • High server memory consumption
  • Difficult scaling

SAS Upload Flow

Browser → Azure Blob Storage
          ↑
     SAS URL from API

Benefits:

  • Faster uploads
  • Reduced server load
  • Better scalability
  • Secure temporary access
  • Ideal for large files

Azure Blob Storage Architecture

Frontend (JavaScript)
        ↓
ASP.NET Core API
        ↓
Generate SAS URL
        ↓
Frontend uploads directly
        ↓
Azure Blob Storage

Step 1: Create Azure Storage Account

Go to:

Create:

  • Storage Account
  • Blob Container
  • Enable Blob Storage

Example container:

uploads

Step 2: Install NuGet Package

Install Azure Blob SDK.

dotnet add package Azure.Storage.Blobs

Step 3: Add Configuration

appsettings.json

{
  "AzureBlob": {
    "ConnectionString": "YOUR_CONNECTION_STRING",
    "ContainerName": "uploads",
    "AccountName": "youraccount",
    "AccountKey": "yourkey"
  }
}

Step 4: Create SAS Service

BlobStorageService.cs

using Azure.Storage;
using Azure.Storage.Blobs;
using Azure.Storage.Sas;

public class BlobStorageService
{
    private readonly IConfiguration _configuration;

    public BlobStorageService(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    public string GenerateUploadSasUrl(string fileName)
    {
        var accountName = _configuration["AzureBlob:AccountName"];
        var accountKey = _configuration["AzureBlob:AccountKey"];
        var containerName = _configuration["AzureBlob:ContainerName"];

        var credential = new StorageSharedKeyCredential(
            accountName,
            accountKey
        );

        var blobUri = new Uri(
            $"https://{accountName}.blob.core.windows.net/{containerName}/{fileName}"
        );

        BlobSasBuilder sasBuilder = new BlobSasBuilder
        {
            BlobContainerName = containerName,
            BlobName = fileName,
            Resource = "b",
            StartsOn = DateTimeOffset.UtcNow,
            ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(15)
        };

        sasBuilder.SetPermissions(BlobSasPermissions.Create |
                                  BlobSasPermissions.Write);

        var sasToken = sasBuilder.ToSasQueryParameters(credential).ToString();

        return $"{blobUri}?{sasToken}";
    }
}

Step 5: Create API Endpoint

UploadController.cs

using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/upload")]
public class UploadController : ControllerBase
{
    private readonly BlobStorageService _blobStorageService;

    public UploadController(BlobStorageService blobStorageService)
    {
        _blobStorageService = blobStorageService;
    }

    [HttpGet("sas-url")]
    public IActionResult GetSasUrl(string fileName)
    {
        var sasUrl = _blobStorageService.GenerateUploadSasUrl(fileName);

        return Ok(new
        {
            uploadUrl = sasUrl
        });
    }
}

Step 6: Register Service

Program.cs

builder.Services.AddScoped<BlobStorageService>();

Step 7: Frontend JavaScript Upload

HTML

<input type="file" id="fileInput" />
<button onclick="uploadFile()">Upload</button>

JavaScript

async function uploadFile() {

    const fileInput = document.getElementById("fileInput");

    const file = fileInput.files[0];

    if (!file) {
        alert("Select file");
        return;
    }

    // Step 1: Get SAS URL
    const response = await fetch(
        `/api/upload/sas-url?fileName=${encodeURIComponent(file.name)}`
    );

    const data = await response.json();

    // Step 2: Upload directly to Azure
    const uploadResponse = await fetch(data.uploadUrl, {
        method: "PUT",
        headers: {
            "x-ms-blob-type": "BlockBlob",
            "Content-Type": file.type
        },
        body: file
    });

    if (uploadResponse.ok) {
        alert("File uploaded successfully");
    } else {
        alert("Upload failed");
    }
}

How It Works

Backend

  • Generates secure temporary URL
  • Defines permissions
  • Sets expiration time

Frontend

  • Requests upload URL
  • Uploads file directly to Azure Blob Storage
  • No file passes through your API server.

Important SAS Permissions

Permission Meaning
Read Download file
Write Modify blob
Create Upload new blob
Delete Remove blob
List List container files

Use minimum required permissions.

Microsoft recommends limiting permissions and expiration scope for security.

Production Security Best Practices

1. Use Short Expiration

Good:

ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(10)

Bad:

ExpiresOn = DateTimeOffset.UtcNow.AddYears(1)

2. Generate URLs Server-Side Only

Never expose:

  • Storage account key
  • Connection string

3. Validate File Types

Example:

string[] allowedExtensions = { ".jpg", ".png", ".pdf" };

4. Use Random File Names

Avoid collisions.

var fileName = $"{Guid.NewGuid()}{extension}";

5. Restrict Permissions

Only grant required access.

Example:

BlobSasPermissions.Create | BlobSasPermissions.Write

NOT:

BlobSasPermissions.All

Large File Upload Optimization

For large files:

  • Use chunk uploads
  • Use parallel uploads
  • Use resumable uploads

Azure Blob Storage supports block-based uploads efficiently.

Common Errors

1. Signature Did Not Match

Usually caused by:

  • Wrong account key
  • Invalid blob path
  • Expired SAS token

This is a common developer issue discussed in Azure community forums.

2. CORS Error

Configure Azure Storage CORS.

Azure Portal:

Storage Account
→ Resource Sharing (CORS)

Add:

Allowed Origins: *
Allowed Methods: PUT, GET
Allowed Headers: *

3. Authentication Failed

Check:

  • SAS expiration
  • Blob permissions
  • Container name

Advanced Production Architecture

Client
   ↓
API Gateway
   ↓
Auth Validation
   ↓
Generate SAS URL
   ↓
Azure Blob Storage

Optional additions:

  • CDN
  • Virus scanning
  • Queue processing
  • Thumbnail generation

User Delegation SAS (Recommended)

Microsoft recommends using User Delegation SAS instead of account-key SAS because it uses Microsoft Entra credentials for better security.

Benefits:

  • Better security
  • No direct account key exposure
  • RBAC integration

Real-World Use Cases

  • Social Media Platforms
    • Image uploads
    • Video uploads
  • Blogging Systems
    • Thumbnail uploads
    • PDF attachments
  • E-Commerce
    • Product image uploads
  • Enterprise Apps
    • Document management
    • Report uploads

Performance Benefits

Traditional Upload SAS Upload
High server load Minimal server load
Slow Faster
Expensive scaling Better scalability
Large memory usage Direct cloud upload

Conclusion

Using Azure Blob Storage with SAS URLs is one of the best approaches for modern scalable applications.

It provides:

  • Secure uploads
  • Faster performance
  • Reduced backend load
  • Better scalability
  • Cloud-native architecture

The combination of:

  • ASP.NET Core backend
  • JavaScript frontend
  • Azure Blob Storage
  • creates a highly scalable and production-ready upload system suitable for enterprise applications.

For official Azure documentation and SDK examples, see:

Azure SAS Overview Documentation

Azure Blob SAS JavaScript Guide

Azure Blob Storage JavaScript SDK

0 Comments Report