Get started with Azure Blob Storage and TypeScript

This article shows you how to connect to Azure Blob Storage by using the Azure Blob Storage client library for JavaScript. Once connected, your code can operate on containers, blobs, and features of the Blob Storage service.

Package (npm) | API reference | Library source code |

Prerequisites

Set up your project

  1. Open a command prompt and change into your project folder. Change YOUR-DIRECTORY to your folder name:

    cd YOUR-DIRECTORY
    
  2. If you don't have a package.json file already in your directory, initialize the project to create the file:

    npm init -y
    
  3. Install TypeScript and the Azure Blob Storage client library for JavaScript with TypeScript types included:

    npm install typescript @azure/storage-blob
    
  4. If you want to use passwordless connections using Microsoft Entra ID, install the Azure Identity client library for JavaScript:

    npm install @azure/identity
    

Authorize access and connect to Blob Storage

Microsoft Entra ID provides the most secure connection by managing the connection identity (managed identity). This passwordless functionality allows you to develop an application that doesn't require any secrets (keys or connection strings) stored in the code.

Set up identity access to the Azure cloud

To connect to Azure without passwords, you need to set up an Azure identity or use an existing identity. Once the identity is set up, make sure to assign the appropriate roles to the identity.

To authorize passwordless access with Microsoft Entra ID, you'll need to use an Azure credential. Which type of credential you need depends on where your application runs. Use this table as a guide.

Environment Method
Developer environment Visual Studio Code
Developer environment Service principal
Azure-hosted apps Azure-hosted apps setup
On-premises On-premises app setup

Set up storage account roles

Your storage resource needs to have one or more of the following Azure RBAC roles assigned to the identity resource you plan to connect with. Setup the Azure Storage roles for each identity you created in the previous step: Azure cloud, local development, on-premises.

After you complete the setup, each identity needs at least one of the appropriate roles:

  • A data access role - such as:

    • Storage Blob Data Reader
    • Storage Blob Data Contributor
  • A resource role - such as:

    • Reader
    • Contributor

Build your application

As you build your application, your code will primarily interact with three types of resources:

  • The storage account, which is the unique top-level namespace for your Azure Storage data.
  • Containers, which organize the blob data in your storage account.
  • Blobs, which store unstructured data like text and binary data.

The following diagram shows the relationship between these resources.

Diagram of Blob storage architecture

Each type of resource is represented by one or more associated JavaScript clients:

Class Description
BlobServiceClient Represents the Blob Storage endpoint for your storage account.
ContainerClient Allows you to manipulate Azure Storage containers and their blobs.
BlobClient Allows you to manipulate Azure Storage blobs.

Create a BlobServiceClient object

The BlobServiceClient object is the top object in the SDK. This client allows you to manipulate the service, containers and blobs.

Once your Azure storage account identity roles and your local environment are set up, create a TypeScript file which includes the @azure/identity package. Create a credential, such as the DefaultAzureCredential, to implement passwordless connections to Blob Storage. Use that credential to authenticate with a BlobServiceClient object.

// connect-with-default-azure-credential.js
// You must set up RBAC for your identity with one of the following roles:
// - Storage Blob Data Reader
// - Storage Blob Data Contributor
import { DefaultAzureCredential } from '@azure/identity';
import { BlobServiceClient } from '@azure/storage-blob';
import * as dotenv from 'dotenv';
dotenv.config();

const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME as string;
if (!accountName) throw Error('Azure Storage accountName not found');

const blobServiceClient = new BlobServiceClient(
  `https://${accountName}.blob.core.chinacloudapi.cn`,
  new DefaultAzureCredential()
);

async function main() {
  const containerName = 'my-container';
  const blobName = 'my-blob';

  const timestamp = Date.now();
  const fileName = `my-new-file-${timestamp}.txt`;

  // create container client
  const containerClient = await blobServiceClient.getContainerClient(
    containerName
  );

  // create blob client
  const blobClient = await containerClient.getBlockBlobClient(blobName);

  // download file
  const downloadResult = await blobClient.downloadToFile(fileName);

  if (downloadResult.errorCode) throw Error(downloadResult.errorCode);

  console.log(
    `${fileName} downloaded ${downloadResult.contentType}, isCurrentVersion: ${downloadResult.isCurrentVersion}`
  );
}

main()
  .then(() => console.log(`success`))
  .catch((err: unknown) => {
    if (err instanceof Error) {
      console.log(err.message);
    }
  });

The dotenv package is used to read your storage account name from a .env file. This file should not be checked into source control. If you use a local service principal as part of your DefaultAzureCredential set up, any security information for that credential will also go into the .env file.

If you plan to deploy the application to servers and clients that run outside of Azure, create one of the credentials that meets your needs.

Create a ContainerClient object

You can create the ContainerClient object either from the BlobServiceClient, or directly.

Create ContainerClient object from BlobServiceClient

Create the ContainerClient object from the BlobServiceClient.

// Azure Storage dependency
import {
  BlobServiceClient,
  StorageSharedKeyCredential
} from '@azure/storage-blob';

// For development environment - include environment variables from .env
import * as dotenv from 'dotenv';
dotenv.config();

// Azure Storage resource name
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME as string;
if (!accountName) throw Error('Azure Storage accountName not found');

// Azure Storage resource key
const accountKey = process.env.AZURE_STORAGE_ACCOUNT_KEY as string;
if (!accountKey) throw Error('Azure Storage accountKey not found');

// Create credential
const sharedKeyCredential = new StorageSharedKeyCredential(
  accountName,
  accountKey
);

const baseUrl = `https://${accountName}.blob.core.chinacloudapi.cn`;
const containerName = `my-container`;

// Create BlobServiceClient
const blobServiceClient = new BlobServiceClient(
  `${baseUrl}`,
  sharedKeyCredential
);

async function main(): Promise<void> {
  try {
    // Create container client
    const containerClient = await blobServiceClient.getContainerClient(
      containerName
    );

    // do something with containerClient...
    let i = 1;

    // List blobs in container
    for await (const blob of containerClient.listBlobsFlat({
      includeMetadata: true,
      includeSnapshots: false,
      includeTags: true,
      includeVersions: false,
      prefix: ''
    })) {
      console.log(`Blob ${i++}: ${blob.name}`);
    }
  } catch (err) {
    console.log(err);
    throw err;
  }
}

main()
  .then(() => console.log(`success`))
  .catch((err: unknown) => {
    if (err instanceof Error) {
      console.log(err.message);
    }
  });

Create ContainerClient directly

// Azure Storage dependency
import { ContainerClient } from '@azure/storage-blob';

// Azure authentication for credential dependency
import { DefaultAzureCredential } from '@azure/identity';

// For development environment - include environment variables from .env
import * as dotenv from 'dotenv';
dotenv.config();

// Azure Storage resource name
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME as string;
if (!accountName) throw Error('Azure Storage accountName not found');

// Azure SDK needs base URL
const baseUrl = `https://${accountName}.blob.core.chinacloudapi.cn`;

// Unique container name
const timeStamp = Date.now();
const containerName = `my-container`;

async function main(): Promise<void> {
  try {
    // create container client from DefaultAzureCredential
    const containerClient = new ContainerClient(
      `${baseUrl}/${containerName}`,
      new DefaultAzureCredential()
    );

    // do something with containerClient...
    let i = 1;

    // List blobs in container
    for await (const blob of containerClient.listBlobsFlat({
      includeMetadata: true,
      includeSnapshots: false,
      includeTags: true,
      includeVersions: false,
      prefix: ''
    })) {
      console.log(`Blob ${i++}: ${blob.name}`);
    }
  } catch (err) {
    console.log(err);
    throw err;
  }
}

main()
  .then(() => console.log(`success`))
  .catch((err: unknown) => {
    if (err instanceof Error) {
      console.log(err.message);
    }
  });

The dotenv package is used to read your storage account name from a .env file. This file should not be checked into source control.

Create a BlobClient object

You can create any of the BlobClient objects, listed below, either from a ContainerClient, or directly.

List of Blob clients:

Create BlobClient object from ContainerClient

// Azure Storage dependency
import {
  BlobClient,
  BlobDownloadHeaders,
  BlobGetPropertiesHeaders,
  BlobGetPropertiesResponse,
  BlockBlobClient,
  ContainerClient
} from '@azure/storage-blob';

// For development environment - include environment variables from .env
import * as dotenv from 'dotenv';
import { getContainerClientFromDefaultAzureCredential } from './auth-get-client';
dotenv.config();

const containerName = `my-container`;
const containerClient: ContainerClient =
  getContainerClientFromDefaultAzureCredential(containerName);

const blobName = `my-blob`;

async function main(containerClient: ContainerClient): Promise<void> {
  // Create BlobClient object
  const blobClient: BlobClient = containerClient.getBlobClient(blobName);

  // do something with blobClient...
  const properties: BlobGetPropertiesHeaders = await blobClient.getProperties();
  if (properties.errorCode) throw Error(properties.errorCode);

  console.log(`Blob ${blobName} properties:`);

  // get BlockBlobClient from blobClient
  const blockBlobClient: BlockBlobClient = blobClient.getBlockBlobClient();

  // do something with blockBlobClient...
  const downloadResponse: BlobDownloadHeaders = await blockBlobClient.download(
    0
  );
  if (downloadResponse.errorCode) throw Error(downloadResponse.errorCode);
}

main(containerClient)
  .then(() => console.log(`success`))
  .catch((err: unknown) => {
    if (err instanceof Error) {
      console.log(err.message);
    }
  });

Create BlobClient directly

// Azure Storage dependency
import {
  BlockBlobClient,
  BlockBlobUploadHeaders,
  BlockBlobUploadResponse
} from '@azure/storage-blob';
import { getBlockBlobClientFromDefaultAzureCredential } from './auth-get-client';

// For development environment - include environment variables from .env
import * as dotenv from 'dotenv';
dotenv.config();

// Container must exist prior to running this script
const containerName = `my-container`;

// Random blob name and contents
const timeStamp = Date.now();
const blobName = `${timeStamp}-my-blob.txt`;
const fileContentsAsString = 'Hello there.';

const blockBlobClient: BlockBlobClient =
  getBlockBlobClientFromDefaultAzureCredential(containerName, blobName);

async function main(
  blockBlobClient: BlockBlobClient
): Promise<BlockBlobUploadHeaders> {
  // Get file url - available before contents are uploaded
  console.log(`blob.url: ${blockBlobClient.url}`);

  // Upload file contents
  const result: BlockBlobUploadHeaders = await blockBlobClient.upload(
    fileContentsAsString,
    fileContentsAsString.length
  );

  if (result.errorCode) throw Error(result.errorCode);

  // Get results
  return result;
}

main(blockBlobClient)
  .then((result) => {
    console.log(result);
    console.log(`success`);
  })
  .catch((err: unknown) => {
    if (err instanceof Error) {
      console.log(err.message);
    }
  });

/*

Response looks like this:

{
  etag: '"0x8DAD247F1F4896E"',
  lastModified: 2022-11-29T20:26:07.000Z,
  contentMD5: <Buffer 9d 6a 29 63 87 20 77 db 67 4a 27 a3 9c 49 2e 61>,
  clientRequestId: 'a07fdd1f-5937-44c7-984f-0699a48a05c0',
  requestId: '3580e726-201e-0045-1a30-0474f6000000',
  version: '2021-04-10',
  date: 2022-11-29T20:26:06.000Z,
  isServerEncrypted: true,
  'content-length': '0',
  server: 'Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0',
  'x-ms-content-crc64': 'BLv7vb1ONT8=',
  body: undefined
}
*/

The dotenv package is used to read your storage account name from a .env file. This file should not be checked into source control.

See also