How to Upload Files to Azure Blob Storage with a REST API

How to Upload Files to Azure Blob Storage with a REST API

The .NET SDK sample works fine in the demo. Then the mobile team needs to upload from Kotlin, and a partner integration needs to upload from a language with no Azure SDK. Both teams need to understand what the SDK is doing underneath, using plain HTTP.

Most guides to a REST API to upload files to Azure Blob Storage stop at the SDK. That’s a problem when the client isn’t running .NET. This guide walks through the raw HTTP calls because that’s what your non-.NET clients will actually use.

Uploading a file to Azure Blob Storage through a REST API means a Put Blob call (or Put Block plus Put Block List for chunks) authorized by a SAS token, with x-ms-blob-type and Content-Length headers set. The scalable pattern issues short-lived SAS URLs from your API and lets clients upload directly to Blob Storage. Filestack can front the same flow with retries, progress, and an embeddable picker.

Blob Storage’s REST surface is smaller than it looks. One auth concept, two upload operations, and a pattern for putting them together that scales past a single client.

Key Takeaways

  • Put Blob uploads a block blob in a single call, up to service limits. Put Block plus Put Block List assembles a file from chunks instead.
  • SAS tokens grant time-boxed, permission-scoped access to a container or blob, which keeps your storage account keys out of any client.
  • Every block blob upload needs the header x-ms-blob-type: BlockBlob and an accurate Content-Length, or the call fails before it writes anything.
  • Direct-from-client uploads keep your API on credential issuance and metadata. The bytes never pass through your servers at all.
  • Block-based chunking allows parallel part upload and per-part retry, which matters far more on an unreliable network than a single large PUT.

Blob Basics, Block Blobs and SAS

Azure Blob Storage supports several blob types, but block blobs are the main one to use for file uploads. A block blob is made up of blocks. Small files can be uploaded in one go, while larger files can be split into multiple blocks and assembled later. Page blobs are designed for random-access data like VHDs, while append blobs are better for log-style data.

A SAS (Shared Access Signature) lets a client access a blob or container without giving it your storage account key. It includes the permissions being granted, an expiry time, and a signature that verifies the token hasn’t been changed.

Your API creates the SAS on the server using a storage key that never leaves your infrastructure. It then gives the client the signed URL it needs to upload the file.

Now that the basic pieces are clear, let’s use them to upload a file with nothing more than an HTTP client.

The Walkthrough, PUT with a SAS URL

The basic flow for a file upload REST API in Azure is simple: your backend creates a SAS URL, and the client uses that URL to send a PUT request directly to Azure Blob Storage with the file as the request body.

# Server-side: issue a SAS URL scoped to one blob, valid for 10 minutes

from azure.storage.blob import BlobServiceClient, generate_blob_sas, BlobSasPermissions

from datetime import datetime, timedelta

account_name = "yourstorageaccount"

account_key = "YOUR_ACCOUNT_KEY"

container_name = "uploads"

blob_name = "photo.jpg"

sas_token = generate_blob_sas(

account_name=account_name,

container_name=container_name,

blob_name=blob_name,

account_key=account_key,

permission=BlobSasPermissions(write=True, create=True),

expiry=datetime.utcnow() + timedelta(minutes=10),

)

upload_url = f"https://{account_name}.blob.core.windows.net/{container_name}/{blob_name}?{sas_token}"

Once the client has that URL, the upload itself is a single PUT with two headers that Azure requires on every block blob write:

curl -X PUT "<https://yourstorageaccount.blob.core.windows.net/uploads/photo.jpg?sv=...&sig=>..." \

-H "x-ms-blob-type: BlockBlob" \

-H "Content-Length: 2048576" \

--data-binary @photo.jpg

x-ms-blob-type: BlockBlob tells Azure what kind of blob it’s writing, and an accurate Content-Length is required for the call to succeed at all. Miss either header and the request fails before a single byte is written.

Put Blob can upload a file in one request, which works well for smaller files. For larger files, you’ll want to use block uploads instead. That’s where blocks come in.

Chunking with Put Block

Put Blob works well up to a point, but sending a very large file in one request can be fragile. If the connection drops near the end, the whole upload may need to start again.

Put Block and Put Block List solve this by splitting the file into smaller pieces. This follows the same basic pattern used by most large-file uploads: split the file, upload the pieces, then put them back together.

Each block gets its own Base64-encoded block ID and is uploaded with a separate PUT request. Once all the blocks are uploaded, a single Put Block List request commits them in the correct order and creates the final blob.

import base64

import requests

BASE_URL = "<https://yourstorageaccount.blob.core.windows.net/uploads/large-file.zip>"

SAS = "?sv=...&sig=..."

CHUNK_SIZE = 4 * 1024 * 1024  # 4MB per block

block_ids = []

with open("large-file.zip", "rb") as f:

index = 0

while chunk := f.read(CHUNK_SIZE):

block_id = base64.b64encode(f"block-{index:05d}".encode()).decode()

block_ids.append(block_id)

requests.put(

f"{BASE_URL}{SAS}&comp=block&blockid={block_id}",

headers={"x-ms-blob-type": "BlockBlob"},

data=chunk,

)

index += 1

# Commit the blocks, in order, into one blob

block_list_xml = "<BlockList>" + "".join(

f"<Latest>{bid}</Latest>" for bid in block_ids

) + "</BlockList>"

requests.put(

f"{BASE_URL}{SAS}&comp=blocklist",

data=block_list_xml,

headers={"Content-Type": "application/xml"},

)

Because each block uses its own request, you can upload multiple blocks at the same time. If one block fails, you only need to retry that block instead of starting the whole upload again. That’s the main advantage over a single large Put Blob request.

Both approaches follow the same basic pattern: the client gets a SAS URL and sends the file directly to Azure Blob Storage. The difference is whether the file goes up in one request or several smaller ones.

Filestack discord

Next, let’s look at that direct-to-storage flow as a complete architecture.

The Direct-From-Client Architecture

Put together, the pattern looks the same no matter which upload method you use. Your API creates a SAS-scoped credential, the client uploads directly to Blob Storage, and a webhook or client callback tells your API when the upload is complete.

This is the core idea behind a good file upload REST API design on Azure: keep your API on the control plane, keep Blob Storage on the data plane, and don’t mix the two.

Diagram showing direct-from-client flow in a rest api to upload file to azure blob storage.

This is also similar to how other cloud providers handle file uploads. The names may change, such as SAS on Azure and presigned URLs on AWS, but the basic architecture is the same: issue short-lived, limited credentials, let the client upload directly to storage, and keep your API server out of the file transfer.

This approach works well for a single application. Larger teams and organizations usually need a few more controls on top of it, which we’ll cover next.

Enterprise Concerns

Key rotation is the first thing to get right as your system grows. If your SAS tokens use an account key and that key is compromised, the tokens created with it are at risk too. Stored access policies give you more control. You can define permissions and an expiry time on the container, create SAS tokens based on that policy, and revoke the policy if something goes wrong.

Private endpoints keep Blob Storage traffic off the public internet by routing it through your virtual network. This can be important for teams with strict network security requirements. Audit logging records who accessed what and when, which becomes more useful as more people and services can create upload credentials.

These concerns also come up when teams compare enterprise file upload solutions. Questions like what’s the best file upload API for enterprise applications and what security certifications do file upload providers offer are worth checking against each provider’s current documentation. Certifications and their scope can change, so it’s better to verify them directly.

Managing key rotation, access policies, and audit logs yourself takes ongoing work. There’s also a managed approach where much of that operational work is handled for you.

The Managed Route, Same Blobs, Better Client

To handle the client side without building everything yourself, you can use a managed file upload API with features like a picker, chunked uploads, and retries. The files can still go directly into your own Azure Blob container.

This means you don’t have to build the SAS flow, block-splitting logic, or retry handling for unreliable connections yourself. Your API can continue to handle credentials and metadata, while the upload service takes care of moving the file.

Filestack supports storing uploads in customer-owned Azure Blob Storage, as well as S3 and GCS. The overall architecture stays the same: your API handles access and metadata, while the file goes directly to your storage.

The file upload API guide covers authentication and upload patterns more generally. You can also check the Filestack storage integration docs for details on connecting Azure Blob Storage.

Now that we’ve covered both approaches, here’s a quick summary of the key points.

Conclusion: Two Operations and a Token

Blob Storage’s REST API comes down to three main pieces: a SAS token for access, Put Blob for files that fit in one request, and Put Block plus Put Block List for larger files.

No matter which upload method you use, the client talks directly to Blob Storage. Your API handles the credentials and records the upload details instead of moving the file itself.

Before using this in production, test the flow with a test container. Create a SAS token, upload a small file with Put Blob, then upload a larger file in blocks. Make sure both files end up in the right place and can be accessed as expected.

Frequently Asked Questions

Which REST operation uploads a file to Azure Blob Storage?

Put Blob for a single-shot upload. Put Block plus Put Block List for a file split into chunks and committed together.

How do clients authenticate uploads?

Through short-lived SAS URLs issued by your API. Storage account keys stay server-side and are never exposed to a client.

Can a managed uploader store into my Azure container?

Yes. Filestack writes directly into customer-owned Azure Blob containers, alongside support for S3 and GCS.

Read More →