azure-storage-blob-ts

npx skills add https://github.com/microsoft/skills --skill azure-storage-blob-ts

@azure/storage-blob (TypeScript/JavaScript)

SDK pour les opérations Azure Blob Storage — upload, download, list et gestion des blobs et conteneurs.

Installation

npm install @azure/storage-blob @azure/identity

Version actuelle : 12.x
Node.js : >= 18.0.0

Variables d'environnement

AZURE_STORAGE_ACCOUNT_NAME=<account-name>
AZURE_STORAGE_ACCOUNT_KEY=<account-key>
# OU chaîne de connexion
AZURE_STORAGE_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=...
AZURE_TOKEN_CREDENTIALS=prod # Requis uniquement si DefaultAzureCredential est utilisé en production

Authentification

Microsoft Entra Token Credential (Recommandé)

import { BlobServiceClient } from "@azure/storage-blob";
import { DefaultAzureCredential, ManagedIdentityCredential } from "@azure/identity";

// Dev local : DefaultAzureCredential. Production : définir AZURE_TOKEN_CREDENTIALS=prod ou AZURE_TOKEN_CREDENTIALS=<specific_credential>
const credential = new DefaultAzureCredential({requiredEnvVars: ["AZURE_TOKEN_CREDENTIALS"]});
// Ou utiliser une credential spécifique directement en production :
// Voir https://learn.microsoft.com/javascript/api/overview/azure/identity-readme?view=azure-node-latest#credential-classes
// const credential = new ManagedIdentityCredential();

const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;
const client = new BlobServiceClient(
  `https://${accountName}.blob.core.windows.net`,
  credential
);

Chaîne de connexion

import { BlobServiceClient } from "@azure/storage-blob";

const client = BlobServiceClient.fromConnectionString(
  process.env.AZURE_STORAGE_CONNECTION_STRING!
);

StorageSharedKeyCredential (Node.js uniquement)

import { BlobServiceClient, StorageSharedKeyCredential } from "@azure/storage-blob";

const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;
const accountKey = process.env.AZURE_STORAGE_ACCOUNT_KEY!;

const sharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey);
const client = new BlobServiceClient(
  `https://${accountName}.blob.core.windows.net`,
  sharedKeyCredential
);

SAS Token

import { BlobServiceClient } from "@azure/storage-blob";

const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;
const sasToken = process.env.AZURE_STORAGE_SAS_TOKEN!; // commence par "?"

const client = new BlobServiceClient(
  `https://${accountName}.blob.core.windows.net${sasToken}`
);

Hiérarchie des clients

BlobServiceClient (niveau compte)
└── ContainerClient (niveau conteneur)
    └── BlobClient (niveau blob)
        ├── BlockBlobClient (block blobs - plus courant)
        ├── AppendBlobClient (blobs append-only)
        └── PageBlobClient (page blobs - VHDs)

Opérations sur les conteneurs

Créer un conteneur

const containerClient = client.getContainerClient("my-container");
await containerClient.create();

// Ou créer s'il n'existe pas
await containerClient.createIfNotExists();

Lister les conteneurs

for await (const container of client.listContainers()) {
  console.log(container.name);
}

// Avec filtre de préfixe
for await (const container of client.listContainers({ prefix: "logs-" })) {
  console.log(container.name);
}

Supprimer un conteneur

await containerClient.delete();
// Ou supprimer s'il existe
await containerClient.deleteIfExists();

Opérations sur les blobs

Upload de blob (Simple)

const containerClient = client.getContainerClient("my-container");
const blockBlobClient = containerClient.getBlockBlobClient("my-file.txt");

// Upload de chaîne
await blockBlobClient.upload("Hello, World!", 13);

// Upload de Buffer
const buffer = Buffer.from("Hello, World!");
await blockBlobClient.upload(buffer, buffer.length);

Upload depuis fichier (Node.js uniquement)

const blockBlobClient = containerClient.getBlockBlobClient("uploaded-file.txt");
await blockBlobClient.uploadFile("/path/to/local/file.txt");

Upload depuis flux (Node.js uniquement)

import * as fs from "fs";

const blockBlobClient = containerClient.getBlockBlobClient("streamed-file.txt");
const readStream = fs.createReadStream("/path/to/local/file.txt");

await blockBlobClient.uploadStream(readStream, 4 * 1024 * 1024, 5, {
  // bufferSize: 4MB, maxConcurrency: 5
  onProgress: (progress) => console.log(`Uploaded ${progress.loadedBytes} bytes`),
});

Upload depuis navigateur

const blockBlobClient = containerClient.getBlockBlobClient("browser-upload.txt");

// Depuis File input
const fileInput = document.getElementById("fileInput") as HTMLInputElement;
const file = fileInput.files![0];
await blockBlobClient.uploadData(file);

// Depuis Blob/ArrayBuffer
const arrayBuffer = new ArrayBuffer(1024);
await blockBlobClient.uploadData(arrayBuffer);

Télécharger un blob

const blobClient = containerClient.getBlobClient("my-file.txt");
const downloadResponse = await blobClient.download();

// Lire en tant que chaîne (navigateur & Node.js)
const downloaded = await streamToText(downloadResponse.readableStreamBody!);

async function streamToText(readable: NodeJS.ReadableStream): Promise<string> {
  const chunks: Buffer[] = [];
  for await (const chunk of readable) {
    chunks.push(Buffer.from(chunk));
  }
  return Buffer.concat(chunks).toString("utf-8");
}

Télécharger vers fichier (Node.js uniquement)

const blockBlobClient = containerClient.getBlockBlobClient("my-file.txt");
await blockBlobClient.downloadToFile("/path/to/local/destination.txt");

Télécharger vers Buffer (Node.js uniquement)

const blockBlobClient = containerClient.getBlockBlobClient("my-file.txt");
const buffer = await blockBlobClient.downloadToBuffer();
console.log(buffer.toString());

Lister les blobs

// Lister tous les blobs
for await (const blob of containerClient.listBlobsFlat()) {
  console.log(blob.name, blob.properties.contentLength);
}

// Lister avec préfixe
for await (const blob of containerClient.listBlobsFlat({ prefix: "logs/" })) {
  console.log(blob.name);
}

// Lister par hiérarchie (répertoires virtuels)
for await (const item of containerClient.listBlobsByHierarchy("/")) {
  if (item.kind === "prefix") {
    console.log(`Directory: ${item.name}`);
  } else {
    console.log(`Blob: ${item.name}`);
  }
}

Supprimer un blob

const blobClient = containerClient.getBlobClient("my-file.txt");
await blobClient.delete();

// Supprimer s'il existe
await blobClient.deleteIfExists();

// Supprimer avec snapshots
await blobClient.delete({ deleteSnapshots: "include" });

Copier un blob

const sourceBlobClient = containerClient.getBlobClient("source.txt");
const destBlobClient = containerClient.getBlobClient("destination.txt");

// Démarrer l'opération de copie
const copyPoller = await destBlobClient.beginCopyFromURL(sourceBlobClient.url);
await copyPoller.pollUntilDone();

Propriétés et métadonnées des blobs

Obtenir les propriétés

const blobClient = containerClient.getBlobClient("my-file.txt");
const properties = await blobClient.getProperties();

console.log("Content-Type:", properties.contentType);
console.log("Content-Length:", properties.contentLength);
console.log("Last Modified:", properties.lastModified);
console.log("ETag:", properties.etag);

Définir les métadonnées

await blobClient.setMetadata({
  author: "John Doe",
  category: "documents",
});

Définir les en-têtes HTTP

await blobClient.setHTTPHeaders({
  blobContentType: "text/plain",
  blobCacheControl: "max-age=3600",
  blobContentDisposition: "attachment; filename=download.txt",
});

Génération de SAS Token (Node.js uniquement)

Générer un SAS Blob

import {
  BlobSASPermissions,
  generateBlobSASQueryParameters,
  StorageSharedKeyCredential,
} from "@azure/storage-blob";

const sharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey);

const sasToken = generateBlobSASQueryParameters(
  {
    containerName: "my-container",
    blobName: "my-file.txt",
    permissions: BlobSASPermissions.parse("r"), // lecture seule
    startsOn: new Date(),
    expiresOn: new Date(Date.now() + 3600 * 1000), // 1 heure
  },
  sharedKeyCredential
).toString();

const sasUrl = `https://${accountName}.blob.core.windows.net/my-container/my-file.txt?${sasToken}`;

Générer un SAS Conteneur

import { ContainerSASPermissions, generateBlobSASQueryParameters } from "@azure/storage-blob";

const sasToken = generateBlobSASQueryParameters(
  {
    containerName: "my-container",
    permissions: ContainerSASPermissions.parse("racwdl"), // read, add, create, write, delete, list
    expiresOn: new Date(Date.now() + 24 * 3600 * 1000), // 24 heures
  },
  sharedKeyCredential
).toString();

Générer un SAS Compte

import {
  AccountSASPermissions,
  AccountSASResourceTypes,
  AccountSASServices,
  generateAccountSASQueryParameters,
} from "@azure/storage-blob";

const sasToken = generateAccountSASQueryParameters(
  {
    services: AccountSASServices.parse("b").toString(), // blob
    resourceTypes: AccountSASResourceTypes.parse("sco").toString(), // service, container, object
    permissions: AccountSASPermissions.parse("rwdlacupi"), // toutes les permissions
    expiresOn: new Date(Date.now() + 24 * 3600 * 1000),
  },
  sharedKeyCredential
).toString();

Types de blobs

Block Blob (Par défaut)

Type le plus courant pour les fichiers texte et binaires.

const blockBlobClient = containerClient.getBlockBlobClient("document.pdf");
await blockBlobClient.uploadFile("/path/to/document.pdf");

Append Blob

Optimisé pour les opérations d'ajout (logs, audit trails).

const appendBlobClient = containerClient.getAppendBlobClient("app.log");

// Créer le append blob
await appendBlobClient.create();

// Ajouter des données
await appendBlobClient.appendBlock("Log entry 1\n", 12);
await appendBlobClient.appendBlock("Log entry 2\n", 12);

Page Blob

Blobs de taille fixe pour lecture/écriture aléatoire (VHDs).

const pageBlobClient = containerClient.getPageBlobClient("disk.vhd");

// Créer un page blob aligné sur 512 octets
await pageBlobClient.create(1024 * 1024); // 1MB

// Écrire des pages (doit être aligné sur 512 octets)
const buffer = Buffer.alloc(512);
await pageBlobClient.uploadPages(buffer, 0, 512);

Gestion des erreurs

import { RestError } from "@azure/storage-blob";

try {
  await containerClient.create();
} catch (error) {
  if (error instanceof RestError) {
    switch (error.statusCode) {
      case 404:
        console.log("Container not found");
        break;
      case 409:
        console.log("Container already exists");
        break;
      case 403:
        console.log("Access denied");
        break;
      default:
        console.error(`Storage error ${error.statusCode}: ${error.message}`);
    }
  }
  throw error;
}

Référence des types TypeScript

import {
  // Clients
  BlobServiceClient,
  ContainerClient,
  BlobClient,
  BlockBlobClient,
  AppendBlobClient,
  PageBlobClient,

  // Authentification
  StorageSharedKeyCredential,
  AnonymousCredential,

  // SAS
  BlobSASPermissions,
  ContainerSASPermissions,
  AccountSASPermissions,
  AccountSASServices,
  AccountSASResourceTypes,
  generateBlobSASQueryParameters,
  generateAccountSASQueryParameters,

  // Options & Réponses
  BlobDownloadResponseParsed,
  BlobUploadCommonResponse,
  ContainerCreateResponse,
  BlobItem,
  ContainerItem,

  // Erreurs
  RestError,
} from "@azure/storage-blob";

Bonnes pratiques

  1. Utiliser DefaultAzureCredential pour le développement local ; utiliser ManagedIdentityCredential ou WorkloadIdentityCredential pour la production
  2. Utiliser le streaming pour les gros fichiersuploadStream/downloadToFile pour les fichiers > 256MB
  3. Définir les types de contenu appropriés — Utiliser setHTTPHeaders pour les types MIME corrects
  4. Utiliser les SAS tokens pour l'accès client — Générer des tokens de courte durée pour les uploads de navigateur
  5. Gérer les erreurs correctement — Vérifier RestError.statusCode pour un traitement spécifique
  6. *Utiliser les méthodes `IfNotExists`** — Pour la création idempotente de conteneur/blob
  7. Fermer les clients — Non requis mais bonne pratique dans les apps longue durée

Différences entre plateformes

Fonctionnalité Node.js Navigateur
StorageSharedKeyCredential
uploadFile()
uploadStream()
downloadToFile()
downloadToBuffer()
uploadData()
Génération SAS
DefaultAzureCredential
Accès anonyme/SAS

Skills similaires