azure-storage-blob-ts
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese@azure/storage-blob (TypeScript/JavaScript)
@azure/storage-blob (TypeScript/JavaScript)
SDK for Azure Blob Storage operations — upload, download, list, and manage blobs and containers.
用于Azure Blob存储操作的SDK —— 上传、下载、列出及管理Blob和容器。
Installation
安装
bash
npm install @azure/storage-blob @azure/identityCurrent Version: 12.x
Node.js: >= 18.0.0
Node.js: >= 18.0.0
bash
npm install @azure/storage-blob @azure/identity当前版本:12.x
Node.js:>= 18.0.0
Node.js:>= 18.0.0
Environment Variables
环境变量
bash
AZURE_STORAGE_ACCOUNT_NAME=<account-name>
AZURE_STORAGE_ACCOUNT_KEY=<account-key>bash
AZURE_STORAGE_ACCOUNT_NAME=<账户名称>
AZURE_STORAGE_ACCOUNT_KEY=<账户密钥>OR connection string
或使用连接字符串
AZURE_STORAGE_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=...
undefinedAZURE_STORAGE_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=...
undefinedAuthentication
身份验证
DefaultAzureCredential (Recommended)
DefaultAzureCredential(推荐)
typescript
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()
);typescript
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()
);Connection String
连接字符串
typescript
import { BlobServiceClient } from "@azure/storage-blob";
const client = BlobServiceClient.fromConnectionString(
process.env.AZURE_STORAGE_CONNECTION_STRING!
);typescript
import { BlobServiceClient } from "@azure/storage-blob";
const client = BlobServiceClient.fromConnectionString(
process.env.AZURE_STORAGE_CONNECTION_STRING!
);StorageSharedKeyCredential (Node.js only)
StorageSharedKeyCredential(仅Node.js)
typescript
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
);typescript
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
SAS令牌
typescript
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}`
);typescript
import { BlobServiceClient } from "@azure/storage-blob";
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME!;
const sasToken = process.env.AZURE_STORAGE_SAS_TOKEN!; // 以"?"开头
const client = new BlobServiceClient(
`https://${accountName}.blob.core.windows.net${sasToken}`
);Client Hierarchy
客户端层级结构
BlobServiceClient (account level)
└── ContainerClient (container level)
└── BlobClient (blob level)
├── BlockBlobClient (block blobs - most common)
├── AppendBlobClient (append-only blobs)
└── PageBlobClient (page blobs - VHDs)BlobServiceClient(账户级别)
└── ContainerClient(容器级别)
└── BlobClient(Blob级别)
├── BlockBlobClient(块Blob - 最常用)
├── AppendBlobClient(追加型Blob)
└── PageBlobClient(页Blob - 虚拟硬盘)Container Operations
容器操作
Create Container
创建容器
typescript
const containerClient = client.getContainerClient("my-container");
await containerClient.create();
// Or create if not exists
await containerClient.createIfNotExists();typescript
const containerClient = client.getContainerClient("my-container");
await containerClient.create();
// 或不存在时创建
await containerClient.createIfNotExists();List Containers
列出容器
typescript
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);
}typescript
for await (const container of client.listContainers()) {
console.log(container.name);
}
// 带前缀过滤
for await (const container of client.listContainers({ prefix: "logs-" })) {
console.log(container.name);
}Delete Container
删除容器
typescript
await containerClient.delete();
// Or delete if exists
await containerClient.deleteIfExists();typescript
await containerClient.delete();
// 或存在时删除
await containerClient.deleteIfExists();Blob Operations
Blob操作
Upload Blob (Simple)
上传Blob(简单方式)
typescript
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);typescript
const containerClient = client.getContainerClient("my-container");
const blockBlobClient = containerClient.getBlockBlobClient("my-file.txt");
// 上传字符串
await blockBlobClient.upload("Hello, World!", 13);
// 上传Buffer
const buffer = Buffer.from("Hello, World!");
await blockBlobClient.upload(buffer, buffer.length);Upload from File (Node.js only)
从文件上传(仅Node.js)
typescript
const blockBlobClient = containerClient.getBlockBlobClient("uploaded-file.txt");
await blockBlobClient.uploadFile("/path/to/local/file.txt");typescript
const blockBlobClient = containerClient.getBlockBlobClient("uploaded-file.txt");
await blockBlobClient.uploadFile("/path/to/local/file.txt");Upload from Stream (Node.js only)
从流上传(仅Node.js)
typescript
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`),
});typescript
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(`已上传 ${progress.loadedBytes} 字节`),
});Upload from Browser
浏览器端上传
typescript
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);typescript
const blockBlobClient = containerClient.getBlockBlobClient("browser-upload.txt");
// 从文件输入框
const fileInput = document.getElementById("fileInput") as HTMLInputElement;
const file = fileInput.files![0];
await blockBlobClient.uploadData(file);
// 从Blob/ArrayBuffer
const arrayBuffer = new ArrayBuffer(1024);
await blockBlobClient.uploadData(arrayBuffer);Download Blob
下载Blob
typescript
const blobClient = containerClient.getBlobClient("my-file.txt");
const downloadResponse = await blobClient.download();
// Read as string (browser & 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");
}typescript
const blobClient = containerClient.getBlobClient("my-file.txt");
const downloadResponse = await blobClient.download();
// 读取为字符串(浏览器 & 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");
}Download to File (Node.js only)
下载到文件(仅Node.js)
typescript
const blockBlobClient = containerClient.getBlockBlobClient("my-file.txt");
await blockBlobClient.downloadToFile("/path/to/local/destination.txt");typescript
const blockBlobClient = containerClient.getBlockBlobClient("my-file.txt");
await blockBlobClient.downloadToFile("/path/to/local/destination.txt");Download to Buffer (Node.js only)
下载到Buffer(仅Node.js)
typescript
const blockBlobClient = containerClient.getBlockBlobClient("my-file.txt");
const buffer = await blockBlobClient.downloadToBuffer();
console.log(buffer.toString());typescript
const blockBlobClient = containerClient.getBlockBlobClient("my-file.txt");
const buffer = await blockBlobClient.downloadToBuffer();
console.log(buffer.toString());List Blobs
列出Blob
typescript
// 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}`);
}
}typescript
// 列出所有Blob
for await (const blob of containerClient.listBlobsFlat()) {
console.log(blob.name, blob.properties.contentLength);
}
// 带前缀过滤
for await (const blob of containerClient.listBlobsFlat({ prefix: "logs/" })) {
console.log(blob.name);
}
// 按层级列出(虚拟目录)
for await (const item of containerClient.listBlobsByHierarchy("/")) {
if (item.kind === "prefix") {
console.log(`目录: ${item.name}`);
} else {
console.log(`Blob: ${item.name}`);
}
}Delete Blob
删除Blob
typescript
const blobClient = containerClient.getBlobClient("my-file.txt");
await blobClient.delete();
// Delete if exists
await blobClient.deleteIfExists();
// Delete with snapshots
await blobClient.delete({ deleteSnapshots: "include" });typescript
const blobClient = containerClient.getBlobClient("my-file.txt");
await blobClient.delete();
// 存在时删除
await blobClient.deleteIfExists();
// 删除包含快照
await blobClient.delete({ deleteSnapshots: "include" });Copy Blob
复制Blob
typescript
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();typescript
const sourceBlobClient = containerClient.getBlobClient("source.txt");
const destBlobClient = containerClient.getBlobClient("destination.txt");
// 启动复制操作
const copyPoller = await destBlobClient.beginCopyFromURL(sourceBlobClient.url);
await copyPoller.pollUntilDone();Blob Properties & Metadata
Blob属性与元数据
Get Properties
获取属性
typescript
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);typescript
const blobClient = containerClient.getBlobClient("my-file.txt");
const properties = await blobClient.getProperties();
console.log("内容类型:", properties.contentType);
console.log("内容长度:", properties.contentLength);
console.log("最后修改时间:", properties.lastModified);
console.log("ETag:", properties.etag);Set Metadata
设置元数据
typescript
await blobClient.setMetadata({
author: "John Doe",
category: "documents",
});typescript
await blobClient.setMetadata({
author: "John Doe",
category: "documents",
});Set HTTP Headers
设置HTTP头
typescript
await blobClient.setHTTPHeaders({
blobContentType: "text/plain",
blobCacheControl: "max-age=3600",
blobContentDisposition: "attachment; filename=download.txt",
});typescript
await blobClient.setHTTPHeaders({
blobContentType: "text/plain",
blobCacheControl: "max-age=3600",
blobContentDisposition: "attachment; filename=download.txt",
});SAS Token Generation (Node.js only)
SAS令牌生成(仅Node.js)
Generate Blob SAS
生成Blob SAS
typescript
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}`;typescript
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"), // 仅读取
startsOn: new Date(),
expiresOn: new Date(Date.now() + 3600 * 1000), // 1小时
},
sharedKeyCredential
).toString();
const sasUrl = `https://${accountName}.blob.core.windows.net/my-container/my-file.txt?${sasToken}`;Generate Container SAS
生成容器SAS
typescript
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 hours
},
sharedKeyCredential
).toString();typescript
import { ContainerSASPermissions, generateBlobSASQueryParameters } from "@azure/storage-blob";
const sasToken = generateBlobSASQueryParameters(
{
containerName: "my-container",
permissions: ContainerSASPermissions.parse("racwdl"), // 读取、添加、创建、写入、删除、列出
expiresOn: new Date(Date.now() + 24 * 3600 * 1000), // 24小时
},
sharedKeyCredential
).toString();Generate Account SAS
生成账户SAS
typescript
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"), // all permissions
expiresOn: new Date(Date.now() + 24 * 3600 * 1000),
},
sharedKeyCredential
).toString();typescript
import {
AccountSASPermissions,
AccountSASResourceTypes,
AccountSASServices,
generateAccountSASQueryParameters,
} from "@azure/storage-blob";
const sasToken = generateAccountSASQueryParameters(
{
services: AccountSASServices.parse("b").toString(), // Blob
resourceTypes: AccountSASResourceTypes.parse("sco").toString(), // 服务、容器、对象
permissions: AccountSASPermissions.parse("rwdlacupi"), // 所有权限
expiresOn: new Date(Date.now() + 24 * 3600 * 1000),
},
sharedKeyCredential
).toString();Blob Types
Blob类型
Block Blob (Default)
块Blob(默认)
Most common type for text and binary files.
typescript
const blockBlobClient = containerClient.getBlockBlobClient("document.pdf");
await blockBlobClient.uploadFile("/path/to/document.pdf");最常用于文本和二进制文件。
typescript
const blockBlobClient = containerClient.getBlockBlobClient("document.pdf");
await blockBlobClient.uploadFile("/path/to/document.pdf");Append Blob
追加Blob
Optimized for append operations (logs, audit trails).
typescript
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);针对追加操作优化(日志、审计追踪)。
typescript
const appendBlobClient = containerClient.getAppendBlobClient("app.log");
// 创建追加Blob
await appendBlobClient.create();
// 追加数据
await appendBlobClient.appendBlock("Log entry 1\n", 12);
await appendBlobClient.appendBlock("Log entry 2\n", 12);Page Blob
页Blob
Fixed-size blobs for random read/write (VHDs).
typescript
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);固定大小的Blob,用于随机读写(虚拟硬盘)。
typescript
const pageBlobClient = containerClient.getPageBlobClient("disk.vhd");
// 创建512字节对齐的页Blob
await pageBlobClient.create(1024 * 1024); // 1MB
// 写入页(必须512字节对齐)
const buffer = Buffer.alloc(512);
await pageBlobClient.uploadPages(buffer, 0, 512);Error Handling
错误处理
typescript
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 { RestError } from "@azure/storage-blob";
try {
await containerClient.create();
} catch (error) {
if (error instanceof RestError) {
switch (error.statusCode) {
case 404:
console.log("容器不存在");
break;
case 409:
console.log("容器已存在");
break;
case 403:
console.log("访问被拒绝");
break;
default:
console.error(`存储错误 ${error.statusCode}: ${error.message}`);
}
}
throw error;
}TypeScript Types Reference
TypeScript类型参考
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";typescript
import {
// 客户端
BlobServiceClient,
ContainerClient,
BlobClient,
BlockBlobClient,
AppendBlobClient,
PageBlobClient,
身份验证
StorageSharedKeyCredential,
AnonymousCredential,
// SAS
BlobSASPermissions,
ContainerSASPermissions,
AccountSASPermissions,
AccountSASServices,
AccountSASResourceTypes,
generateBlobSASQueryParameters,
generateAccountSASQueryParameters,
// 选项与响应
BlobDownloadResponseParsed,
BlobUploadCommonResponse,
ContainerCreateResponse,
BlobItem,
ContainerItem,
// 错误
RestError,
} from "@azure/storage-blob";Best Practices
最佳实践
- Use DefaultAzureCredential — Prefer AAD over connection strings/keys
- Use streaming for large files — /
uploadStreamfor files > 256MBdownloadToFile - Set appropriate content types — Use for correct MIME types
setHTTPHeaders - Use SAS tokens for client access — Generate short-lived tokens for browser uploads
- Handle errors gracefully — Check for specific handling
RestError.statusCode - Use methods — For idempotent container/blob creation
*IfNotExists - Close clients — Not required but good practice in long-running apps
- 使用DefaultAzureCredential —— 优先选择AAD而非连接字符串/密钥
- 大文件使用流式传输 —— 对于大于256MB的文件,使用/
uploadStreamdownloadToFile - 设置合适的内容类型 —— 使用设置正确的MIME类型
setHTTPHeaders - 客户端访问使用SAS令牌 —— 为浏览器上传生成短期令牌
- 优雅处理错误 —— 检查进行针对性处理
RestError.statusCode - 使用方法 —— 实现幂等的容器/blob创建
*IfNotExists - 关闭客户端 —— 非强制要求,但在长期运行的应用中是良好实践
Platform Differences
平台差异
| Feature | Node.js | Browser |
|---|---|---|
| ✅ | ❌ |
| ✅ | ❌ |
| ✅ | ❌ |
| ✅ | ❌ |
| ✅ | ❌ |
| ✅ | ✅ |
| SAS generation | ✅ | ❌ |
| DefaultAzureCredential | ✅ | ❌ |
| Anonymous/SAS access | ✅ | ✅ |
| 功能 | Node.js | 浏览器 |
|---|---|---|
| ✅ | ❌ |
| ✅ | ❌ |
| ✅ | ❌ |
| ✅ | ❌ |
| ✅ | ❌ |
| ✅ | ✅ |
| SAS生成 | ✅ | ❌ |
| DefaultAzureCredential | ✅ | ❌ |
| 匿名/SAS访问 | ✅ | ✅ |