mcpField
A
azure-storage-blob-ts

azure-storage-blob-ts

github.com/sickn33云与 DevOps48.7k57 次安装今天更新
代码仓库

关于 azure-storage-blob-ts

azure-storage-blob-ts 是使用 @azure/storage-blob SDK 通过 TypeScript 或 JavaScript 管理 Azure Blob Storage 的技能。内容涵盖容器和 Blob 操作、身份验证、元数据与 SAS Token,并说明 Node.js 和浏览器的差异。

主要功能

  1. 01创建、列出和删除容器
  2. 02上传、下载、复制和删除 Blob
  3. 03列出 Blob 并读取其属性
  4. 04设置 Blob 元数据和 HTTP 标头
  5. 05介绍身份验证和 SAS Token 选项

适用场景

  1. 01将应用文件上传到 Blob Storage
  2. 02列出或获取已存储的 Blob
  3. 03管理容器内容和元数据
  4. 04提供限时 SAS 访问

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/sickn33/agentic-awesome-skills --skill azure-storage-blob-ts

安装后在 Claude Code 中输入/azure-storage-blob-ts确认已加载。

详细介绍

@azure/storage-blob (TypeScript/JavaScript)

用于 Azure Blob Storage 操作的 SDK——上传、下载、列出和管理 Blob 与容器。

安装

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

示例使用 12.x API 系列。请固定兼容的 SDK 版本,并使用软件包 engines 中当前受支持的 Node 运行时;这并不表示使用最新版本。

环境变量

AZURE_STORAGE_ACCOUNT_NAME=<account-name>
AZURE_STORAGE_ACCOUNT_KEY=<account-key>
# OR connection string
AZURE_STORAGE_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=...

身份验证

DefaultAzureCredential(推荐)
import { BlobServiceClient } from "@azure/storage-blob";
import { DefaultAzureCredential } from "@azure/identity";

const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;
const client = new BlobServiceClient(
  `https://${accountName}.blob.core.windows.net`,
  new DefaultAzureCredential()
);
连接字符串
import { BlobServiceClient } from "@azure/storage-blob";

const client = BlobServiceClient.fromConnectionString(
  process.env.AZURE_STORAGE_CONNECTION_STRING!
);
StorageSharedKeyCredential(仅限 Node.js)
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 令牌
import { BlobServiceClient } from "@azure/storage-blob";

const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;
const sasToken = process.env.AZURE_STORAGE_SAS_TOKEN!; // starts with "?"

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

客户端层级

BlobServiceClient (account level)
└── ContainerClient (container level)
    └── BlobClient (blob level)
        ├── BlockBlobClient (block blobs - most common)
        ├── AppendBlobClient (append-only blobs)
        └── PageBlobClient (page blobs - VHDs)

选择权限最小的身份或 SAS、较短的过期时间,并仅通过 HTTPS 访问;在支持的情况下,优先使用用户委托 SAS。切勿在浏览器包或日志中暴露账户密钥或签名 URL。删除或覆盖前,请确认账户、容器和 Blob 的具体对象。setMetadata/setHTTPHeaders 会替换字段:请保留必需的现有值,并在需要时使用条件 ETag。这些示例是彼此独立的操作,不应不加判断地按顺序执行。

容器操作

创建容器
const containerClient = client.getContainerClient("my-container");
await containerClient.create();

// Or create if not exists
await containerClient.createIfNotExists();
列出容器
for await (const container of client.listContainers()) {
  console.log(container.name);
}

// With prefix filter
for await (const container of client.listContainers({ prefix: "logs-" })) {
  console.log(container.name);
}
删除容器
await containerClient.delete();
// Or delete if exists
await containerClient.deleteIfExists();

Blob 操作

上传 Blob(简单方式)
const containerClient = client.getContainerClient("my-container");
const blockBlobClient = containerClient.getBlockBlobClient("my-file.txt");

// Upload string
await blockBlobClient.upload("Hello, World!", 13);

// Upload Buffer
const buffer = Buffer.from("Hello, World!");
await blockBlobClient.upload(buffer, buffer.length);
从文件上传(仅限 Node.js)
const blockBlobClient = containerClient.getBlockBlobClient("uploaded-file.txt");
await blockBlobClient.uploadFile("/path/to/local/file.txt");
从流上传(仅限 Node.js)
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`),
});
从浏览器上传
const blockBlobClient = containerClient.getBlockBlobClient("browser-upload.txt");

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

// From Blob/ArrayBuffer
const arrayBuffer = new ArrayBuffer(1024);
await blockBlobClient.uploadData(arrayBuffer);
下载 Blob
const blobClient = containerClient.getBlobClient("my-file.txt");
const downloadResponse = await blobClient.download();

// Read as string (Node.js only; bounded small blobs)
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");
}

在浏览器中,请使用响应的 blobBody Promise,并在大小限制内读取其文本;readableStreamBody 和 Buffer 仅适用于 Node.js。

下载到文件(仅限 Node.js)
const blockBlobClient = containerClient.getBlockBlobClient("my-file.txt");
await blockBlobClient.downloadToFile("/path/to/local/destination.txt");
下载到 Buffer(仅限 Node.js)
const blockBlobClient = containerClient.getBlockBlobClient("my-file.txt");
const buffer = await blockBlobClient.downloadToBuffer();
console.log(buffer.toString());
列出 Blob
// List all blobs
for await (const blob of containerClient.listBlobsFlat()) {
  console.log(blob.name, blob.properties.contentLength);
}

// List with prefix
for await (const blob of containerClient.listBlobsFlat({ prefix: "logs/" })) {
  console.log(blob.name);
}

// List by hierarchy (virtual directories)
for await (const item of containerClient.listBlobsByHierarchy("/")) {
  if (item.kind === "prefix") {
    console.log(`Directory: ${item.name}`);
  } else {
    console.log(`Blob: ${item.name}`);
  }
}
删除 Blob
const blobClient = containerClient.getBlobClient("my-file.txt");
await blobClient.delete();

// Delete if exists
await blobClient.deleteIfExists();

// Delete with snapshots
await blobClient.delete({ deleteSnapshots: "include" });
复制 Blob
const sourceBlobClient = containerClient.getBlobClient("source.txt");
const destBlobClient = containerClient.getBlobClient("destination.txt");

// Start copy operation
const copyPoller = await destBlobClient.beginCopyFromURL(sourceBlobClient.url);
await copyPoller.pollUntilDone();

Blob 属性与元数据

获取属性
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);
设置元数据
await blobClient.setMetadata({
  author: "John Doe",
  category: "documents",
});
设置 HTTP 标头
await blobClient.setHTTPHeaders({
  blobContentType: "text/plain",
  blobCacheControl: "max-age=3600",
  blobContentDisposition: "attachment; filename=download.txt",
});

生成 SAS 令牌(仅限 Node.js)

生成 Blob SAS
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"), // read only
    startsOn: new Date(),
    expiresOn: new Date(Date.now() + 3600 * 1000), // 1 hour
  },
  sharedKeyCredential
).toString();

const sasUrl = `https://${accountName}.blob.core.windows.net/my-container/my-file.txt?${sasToken}`;
生成容器 SAS
import { ContainerSASPermissions, generateBlobSASQueryParameters } from "@azure/storage-blob";

const sasToken = generateBlobSASQueryParameters(
  {
    containerName: "my-container",
    permissions: ContainerSASPermissions.parse("rl"), // read/list example; grant writes only when requested
    expiresOn: new Date(Date.now() + 24 * 3600 * 1000), // 24 hours
  },
  sharedKeyCredential
).toString();
生成账户 SAS
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("rl"), // read/list only; avoid account-wide SAS when blob scope suffices
    expiresOn: new Date(Date.now() + 24 * 3600 * 1000),
  },
  sharedKeyCredential
).toString();

Blob 类型

块 Blob(默认)

最常见的文本和二进制文件类型。

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

针对追加操作(日志、审计记录)进行了优化。

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

// Create the append blob
await appendBlobClient.create();

// Append data
await appendBlobClient.appendBlock("Log entry 1\n", 12);
await appendBlobClient.appendBlock("Log entry 2\n", 12);
页 Blob

用于随机读写的固定大小 Blob(VHD)。

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

// Create 512-byte aligned page blob
await pageBlobClient.create(1024 * 1024); // 1MB

// Write pages (must be 512-byte aligned)
const buffer = Buffer.alloc(512);
await pageBlobClient.uploadPages(buffer, 0, 512);

错误处理

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;
}

TypeScript 类型参考

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

  // Authentication
  StorageSharedKeyCredential,
  AnonymousCredential,

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

  // Options & Responses
  BlobDownloadResponseParsed,
  BlobUploadCommonResponse,
  ContainerCreateResponse,
  BlobItem,
  ContainerItem,

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

最佳实践

  1. 使用 DefaultAzureCredential — 优先使用 AAD,而不是连接字符串或密钥
  2. 大文件使用流式处理 — 对于大于 256MB 的文件,使用 uploadStream/downloadToFile
  3. 设置适当的内容类型 — 使用 setHTTPHeaders 设置正确的 MIME 类型
  4. 使用 SAS 令牌供客户端访问 — 为浏览器上传生成短期令牌
  5. 妥善处理错误 — 检查 RestError.statusCode,以进行相应处理
  6. 使用 *IfNotExists 方法 — 实现幂等的容器或 Blob 创建
  7. 生命周期 — 仅使用固定客户端实际公开的生命周期方法;不要虚构 close() 调用

平台差异

功能Node.js浏览器
StorageSharedKeyCredential✅❌
uploadFile()✅❌
uploadStream()✅❌
downloadToFile()✅❌
downloadToBuffer()✅❌
uploadData()✅✅
SAS 生成✅❌
DefaultAzureCredential✅❌
匿名/SAS 访问✅✅

适用场景

当需要执行概述中所述的工作流或操作时,可以使用此技能。

限制

  • 仅当任务明确符合上述范围时才使用此技能。
  • 请勿将输出视为环境特定验证、测试或专家审查的替代品。
  • 如果缺少必要的输入、权限、安全边界或成功标准,请停止并请求澄清。

评论

支持 Markdown