|
Add this skill
npx mdskills install sickn33/azure-storage-blob-tsComprehensive reference doc for Azure Blob SDK but lacks agent-specific trigger conditions and workflows
1---2name: azure-storage-blob-ts3description: |4 Azure Blob Storage JavaScript/TypeScript SDK (@azure/storage-blob) for blob operations. Use for uploading, downloading, listing, and managing blobs and containers. Supports block blobs, append blobs, page blobs, SAS tokens, and streaming. Triggers: "blob storage", "@azure/storage-blob", "BlobServiceClient", "ContainerClient", "upload blob", "download blob", "SAS token", "block blob".5package: "@azure/storage-blob"6---78# @azure/storage-blob (TypeScript/JavaScript)910SDK for Azure Blob Storage operations — upload, download, list, and manage blobs and containers.1112## Installation1314```bash15npm install @azure/storage-blob @azure/identity16```1718**Current Version**: 12.x19**Node.js**: >= 18.0.02021## Environment Variables2223```bash24AZURE_STORAGE_ACCOUNT_NAME=<account-name>25AZURE_STORAGE_ACCOUNT_KEY=<account-key>26# OR connection string27AZURE_STORAGE_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=...28```2930## Authentication3132### DefaultAzureCredential (Recommended)3334```typescript35import { BlobServiceClient } from "@azure/storage-blob";36import { DefaultAzureCredential } from "@azure/identity";3738const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;39const client = new BlobServiceClient(40 `https://${accountName}.blob.core.windows.net`,41 new DefaultAzureCredential()42);43```4445### Connection String4647```typescript48import { BlobServiceClient } from "@azure/storage-blob";4950const client = BlobServiceClient.fromConnectionString(51 process.env.AZURE_STORAGE_CONNECTION_STRING!52);53```5455### StorageSharedKeyCredential (Node.js only)5657```typescript58import { BlobServiceClient, StorageSharedKeyCredential } from "@azure/storage-blob";5960const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;61const accountKey = process.env.AZURE_STORAGE_ACCOUNT_KEY!;6263const sharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey);64const client = new BlobServiceClient(65 `https://${accountName}.blob.core.windows.net`,66 sharedKeyCredential67);68```6970### SAS Token7172```typescript73import { BlobServiceClient } from "@azure/storage-blob";7475const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;76const sasToken = process.env.AZURE_STORAGE_SAS_TOKEN!; // starts with "?"7778const client = new BlobServiceClient(79 `https://${accountName}.blob.core.windows.net${sasToken}`80);81```8283## Client Hierarchy8485```86BlobServiceClient (account level)87└── ContainerClient (container level)88 └── BlobClient (blob level)89 ├── BlockBlobClient (block blobs - most common)90 ├── AppendBlobClient (append-only blobs)91 └── PageBlobClient (page blobs - VHDs)92```9394## Container Operations9596### Create Container9798```typescript99const containerClient = client.getContainerClient("my-container");100await containerClient.create();101102// Or create if not exists103await containerClient.createIfNotExists();104```105106### List Containers107108```typescript109for await (const container of client.listContainers()) {110 console.log(container.name);111}112113// With prefix filter114for await (const container of client.listContainers({ prefix: "logs-" })) {115 console.log(container.name);116}117```118119### Delete Container120121```typescript122await containerClient.delete();123// Or delete if exists124await containerClient.deleteIfExists();125```126127## Blob Operations128129### Upload Blob (Simple)130131```typescript132const containerClient = client.getContainerClient("my-container");133const blockBlobClient = containerClient.getBlockBlobClient("my-file.txt");134135// Upload string136await blockBlobClient.upload("Hello, World!", 13);137138// Upload Buffer139const buffer = Buffer.from("Hello, World!");140await blockBlobClient.upload(buffer, buffer.length);141```142143### Upload from File (Node.js only)144145```typescript146const blockBlobClient = containerClient.getBlockBlobClient("uploaded-file.txt");147await blockBlobClient.uploadFile("/path/to/local/file.txt");148```149150### Upload from Stream (Node.js only)151152```typescript153import * as fs from "fs";154155const blockBlobClient = containerClient.getBlockBlobClient("streamed-file.txt");156const readStream = fs.createReadStream("/path/to/local/file.txt");157158await blockBlobClient.uploadStream(readStream, 4 * 1024 * 1024, 5, {159 // bufferSize: 4MB, maxConcurrency: 5160 onProgress: (progress) => console.log(`Uploaded ${progress.loadedBytes} bytes`),161});162```163164### Upload from Browser165166```typescript167const blockBlobClient = containerClient.getBlockBlobClient("browser-upload.txt");168169// From File input170const fileInput = document.getElementById("fileInput") as HTMLInputElement;171const file = fileInput.files![0];172await blockBlobClient.uploadData(file);173174// From Blob/ArrayBuffer175const arrayBuffer = new ArrayBuffer(1024);176await blockBlobClient.uploadData(arrayBuffer);177```178179### Download Blob180181```typescript182const blobClient = containerClient.getBlobClient("my-file.txt");183const downloadResponse = await blobClient.download();184185// Read as string (browser & Node.js)186const downloaded = await streamToText(downloadResponse.readableStreamBody!);187188async function streamToText(readable: NodeJS.ReadableStream): Promise<string> {189 const chunks: Buffer[] = [];190 for await (const chunk of readable) {191 chunks.push(Buffer.from(chunk));192 }193 return Buffer.concat(chunks).toString("utf-8");194}195```196197### Download to File (Node.js only)198199```typescript200const blockBlobClient = containerClient.getBlockBlobClient("my-file.txt");201await blockBlobClient.downloadToFile("/path/to/local/destination.txt");202```203204### Download to Buffer (Node.js only)205206```typescript207const blockBlobClient = containerClient.getBlockBlobClient("my-file.txt");208const buffer = await blockBlobClient.downloadToBuffer();209console.log(buffer.toString());210```211212### List Blobs213214```typescript215// List all blobs216for await (const blob of containerClient.listBlobsFlat()) {217 console.log(blob.name, blob.properties.contentLength);218}219220// List with prefix221for await (const blob of containerClient.listBlobsFlat({ prefix: "logs/" })) {222 console.log(blob.name);223}224225// List by hierarchy (virtual directories)226for await (const item of containerClient.listBlobsByHierarchy("/")) {227 if (item.kind === "prefix") {228 console.log(`Directory: ${item.name}`);229 } else {230 console.log(`Blob: ${item.name}`);231 }232}233```234235### Delete Blob236237```typescript238const blobClient = containerClient.getBlobClient("my-file.txt");239await blobClient.delete();240241// Delete if exists242await blobClient.deleteIfExists();243244// Delete with snapshots245await blobClient.delete({ deleteSnapshots: "include" });246```247248### Copy Blob249250```typescript251const sourceBlobClient = containerClient.getBlobClient("source.txt");252const destBlobClient = containerClient.getBlobClient("destination.txt");253254// Start copy operation255const copyPoller = await destBlobClient.beginCopyFromURL(sourceBlobClient.url);256await copyPoller.pollUntilDone();257```258259## Blob Properties & Metadata260261### Get Properties262263```typescript264const blobClient = containerClient.getBlobClient("my-file.txt");265const properties = await blobClient.getProperties();266267console.log("Content-Type:", properties.contentType);268console.log("Content-Length:", properties.contentLength);269console.log("Last Modified:", properties.lastModified);270console.log("ETag:", properties.etag);271```272273### Set Metadata274275```typescript276await blobClient.setMetadata({277 author: "John Doe",278 category: "documents",279});280```281282### Set HTTP Headers283284```typescript285await blobClient.setHTTPHeaders({286 blobContentType: "text/plain",287 blobCacheControl: "max-age=3600",288 blobContentDisposition: "attachment; filename=download.txt",289});290```291292## SAS Token Generation (Node.js only)293294### Generate Blob SAS295296```typescript297import {298 BlobSASPermissions,299 generateBlobSASQueryParameters,300 StorageSharedKeyCredential,301} from "@azure/storage-blob";302303const sharedKeyCredential = new StorageSharedKeyCredential(accountName, accountKey);304305const sasToken = generateBlobSASQueryParameters(306 {307 containerName: "my-container",308 blobName: "my-file.txt",309 permissions: BlobSASPermissions.parse("r"), // read only310 startsOn: new Date(),311 expiresOn: new Date(Date.now() + 3600 * 1000), // 1 hour312 },313 sharedKeyCredential314).toString();315316const sasUrl = `https://${accountName}.blob.core.windows.net/my-container/my-file.txt?${sasToken}`;317```318319### Generate Container SAS320321```typescript322import { ContainerSASPermissions, generateBlobSASQueryParameters } from "@azure/storage-blob";323324const sasToken = generateBlobSASQueryParameters(325 {326 containerName: "my-container",327 permissions: ContainerSASPermissions.parse("racwdl"), // read, add, create, write, delete, list328 expiresOn: new Date(Date.now() + 24 * 3600 * 1000), // 24 hours329 },330 sharedKeyCredential331).toString();332```333334### Generate Account SAS335336```typescript337import {338 AccountSASPermissions,339 AccountSASResourceTypes,340 AccountSASServices,341 generateAccountSASQueryParameters,342} from "@azure/storage-blob";343344const sasToken = generateAccountSASQueryParameters(345 {346 services: AccountSASServices.parse("b").toString(), // blob347 resourceTypes: AccountSASResourceTypes.parse("sco").toString(), // service, container, object348 permissions: AccountSASPermissions.parse("rwdlacupi"), // all permissions349 expiresOn: new Date(Date.now() + 24 * 3600 * 1000),350 },351 sharedKeyCredential352).toString();353```354355## Blob Types356357### Block Blob (Default)358359Most common type for text and binary files.360361```typescript362const blockBlobClient = containerClient.getBlockBlobClient("document.pdf");363await blockBlobClient.uploadFile("/path/to/document.pdf");364```365366### Append Blob367368Optimized for append operations (logs, audit trails).369370```typescript371const appendBlobClient = containerClient.getAppendBlobClient("app.log");372373// Create the append blob374await appendBlobClient.create();375376// Append data377await appendBlobClient.appendBlock("Log entry 1\n", 12);378await appendBlobClient.appendBlock("Log entry 2\n", 12);379```380381### Page Blob382383Fixed-size blobs for random read/write (VHDs).384385```typescript386const pageBlobClient = containerClient.getPageBlobClient("disk.vhd");387388// Create 512-byte aligned page blob389await pageBlobClient.create(1024 * 1024); // 1MB390391// Write pages (must be 512-byte aligned)392const buffer = Buffer.alloc(512);393await pageBlobClient.uploadPages(buffer, 0, 512);394```395396## Error Handling397398```typescript399import { RestError } from "@azure/storage-blob";400401try {402 await containerClient.create();403} catch (error) {404 if (error instanceof RestError) {405 switch (error.statusCode) {406 case 404:407 console.log("Container not found");408 break;409 case 409:410 console.log("Container already exists");411 break;412 case 403:413 console.log("Access denied");414 break;415 default:416 console.error(`Storage error ${error.statusCode}: ${error.message}`);417 }418 }419 throw error;420}421```422423## TypeScript Types Reference424425```typescript426import {427 // Clients428 BlobServiceClient,429 ContainerClient,430 BlobClient,431 BlockBlobClient,432 AppendBlobClient,433 PageBlobClient,434435 // Authentication436 StorageSharedKeyCredential,437 AnonymousCredential,438439 // SAS440 BlobSASPermissions,441 ContainerSASPermissions,442 AccountSASPermissions,443 AccountSASServices,444 AccountSASResourceTypes,445 generateBlobSASQueryParameters,446 generateAccountSASQueryParameters,447448 // Options & Responses449 BlobDownloadResponseParsed,450 BlobUploadCommonResponse,451 ContainerCreateResponse,452 BlobItem,453 ContainerItem,454455 // Errors456 RestError,457} from "@azure/storage-blob";458```459460## Best Practices4614621. **Use DefaultAzureCredential** — Prefer AAD over connection strings/keys4632. **Use streaming for large files** — `uploadStream`/`downloadToFile` for files > 256MB4643. **Set appropriate content types** — Use `setHTTPHeaders` for correct MIME types4654. **Use SAS tokens for client access** — Generate short-lived tokens for browser uploads4665. **Handle errors gracefully** — Check `RestError.statusCode` for specific handling4676. **Use `*IfNotExists` methods** — For idempotent container/blob creation4687. **Close clients** — Not required but good practice in long-running apps469470## Platform Differences471472| Feature | Node.js | Browser |473|---------|---------|---------|474| `StorageSharedKeyCredential` | ✅ | ❌ |475| `uploadFile()` | ✅ | ❌ |476| `uploadStream()` | ✅ | ❌ |477| `downloadToFile()` | ✅ | ❌ |478| `downloadToBuffer()` | ✅ | ❌ |479| `uploadData()` | ✅ | ✅ |480| SAS generation | ✅ | ❌ |481| DefaultAzureCredential | ✅ | ❌ |482| Anonymous/SAS access | ✅ | ✅ |483
Full transparency — inspect the skill content before installing.