开始使用 Azure Blob 存储和 JavaScript
本文介绍如何使用适用于 JavaScript 的 Azure Blob 存储客户端库 v12 连接到 Azure Blob 存储。 连接后,可以针对 Blob 存储服务的容器、Blob 和功能运行代码。
示例代码片段在 GitHub 中作为可运行 Node.js 文件提供。
先决条件
- Azure 订阅 - 创建试用订阅。
- Azure 存储帐户 - 创建存储帐户
- Node.js LTS
- 对于客户端(浏览器)应用程序,需要安装捆绑工具。
设置项目
请打开命令提示符并更改为你的项目文件夹。 将
YOUR-DIRECTORY
更改为你的文件夹名称:cd YOUR-DIRECTORY
如果目录中没有
package.json
文件,请初始化项目以创建该文件:npm init -y
安装适用于 JavaScript 的 Azure Blob 存储客户端库:
npm install @azure/storage-blob
如果要通过 Microsoft Entra ID 使用无密码连接,请安装适用于 JavaScript 的 Azure 标识客户端库:
npm install @azure/identity
授予访问权限并连接到 Blob 存储
Microsoft Entra ID 通过管理连接标识(托管标识)提供最安全的连接。 此无密码功能使你可以开发不需要存储在代码中的任何机密(密钥或连接字符串)的应用程序。
设置对 Azure 云的标识访问权限
若要在没有密码的情况下连接到 Azure,需要设置 Azure 标识或使用现有标识。 设置标识后,请确保为标识分配相应的角色。
若要使用 Microsoft Entra ID 授权无密码访问,需要使用 Azure 凭据。 需要哪种类型的凭据取决于应用程序的运行位置。 使用此表作为指南。
环境 | 方法 |
---|---|
开发人员环境 | Visual Studio Code |
开发人员环境 | 服务主体 |
Azure 托管的应用 | Azure 托管的应用设置 |
本地 | 本地应用设置 |
设置存储帐户角色
你的存储资源需要将以下一个或多个 Azure RBAC 角色分配给你计划连接的标识资源。 为在上一步中创建的每个标识设置 Azure 存储角色:Azure 云、本地开发、本地。
完成设置后,每个标识至少需要其中一个相应角色:
生成应用程序
在生成应用程序时,代码主要与三种类型的资源交互:
- 存储帐户,它是 Azure 存储数据的唯一顶级命名空间。
- 容器,用于组织存储帐户中的 Blob 数据。
- Blob,用于存储非结构化数据,例如文本和二进制数据。
以下图示显示了这些资源之间的关系。
每种类型的资源由一个或多个关联的 JavaScript 客户端表示:
类 | 说明 |
---|---|
BlobServiceClient | 表示存储帐户的 Blob 存储终结点。 |
ContainerClient | 允许操作 Azure 存储容器及其 Blob。 |
BlobClient | 允许操作 Azure 存储 Blob。 |
创建 BlobServiceClient 对象
BlobServiceClient 对象是 SDK 中的顶级对象。 此客户端允许操作服务、容器和 Blob。
设置 Azure 存储帐户标识角色和本地环境后,创建包含 @azure/identity
包的 JavaScript 文件。 创建凭据(例如 DefaultAzureCredential),以实现与 Blob 存储的无密码连接。 使用该凭据通过 BlobServiceClient 对象进行身份验证。
// connect-with-default-azure-credential.js
const { BlobServiceClient } = require('@azure/storage-blob');
const { DefaultAzureCredential } = require('@azure/identity');
require('dotenv').config()
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
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 = 'REPLACE-WITH-EXISTING-CONTAINER-NAME';
const blobName = 'REPLACE-WITH-EXISTING-BLOB-NAME';
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
await blobClient.downloadToFile(fileName);
console.log(`${fileName} downloaded`);
}
main()
.then(() => console.log(`done`))
.catch((ex) => console.log(`error: ${ex.message}`));
dotenv
包用于从 .env
文件中读取存储帐户名称。 不应将此文件签入到源代码管理中。 如果使用本地服务主体作为 DefaultAzureCredential 设置的一部分,该凭据的任何安全信息也将进入 .env
文件。
如果你打算将应用程序部署到在 Azure 外部运行的服务器和客户端,请创建符合需要的凭据之一。
创建 ContainerClient 对象
可以从 BlobServiceClient 创建 ContainerClient 对象,或直接创建。
从 BlobServiceClient 创建 ContainerClient 对象
从 BlobServiceClient 创建 ContainerClient 对象。
// Azure Storage dependency
const {
StorageSharedKeyCredential,
BlobServiceClient,
} = require("@azure/storage-blob");
// For development environment - include environment variables from .env
require("dotenv").config();
// Azure Storage resource name
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
if (!accountName) throw Error("Azure Storage accountName not found");
// Azure Storage resource key
const accountKey = process.env.AZURE_STORAGE_ACCOUNT_KEY;
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() {
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()) {
console.log(`Blob ${i++}: ${blob.name}`);
}
} catch (err) {
console.log(err);
throw err;
}
}
main()
.then(() => console.log(`done`))
.catch((ex) => console.log(ex.message));
直接创建 ContainerClient
// Azure Storage dependency
const {
ContainerClient
} = require("@azure/storage-blob");
// Azure authentication for credential dependency
const { DefaultAzureCredential } = require('@azure/identity');
// For development environment - include environment variables from .env
require("dotenv").config();
// Azure Storage resource name
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
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 = `test`;
async function main() {
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()) {
console.log(`Blob ${i++}: ${blob.name}`);
}
} catch (err) {
console.log(err);
throw err;
}
}
main()
.then(() => console.log(`done`))
.catch((ex) => console.log(ex.message));
dotenv
包用于从 .env
文件中读取存储帐户名称。 不应将此文件签入到源代码管理中。
创建 BlobClient 对象
可以从 ContainerClient 创建下面列出的任何 BlobClient 对象,或直接创建。
Blob 客户端列表:
从 ContainerClient 创建 BlobClient 对象
// Azure Storage dependency
const {
StorageSharedKeyCredential,
ContainerClient
} = require("@azure/storage-blob");
// For development environment - include environment variables from .env
require("dotenv").config();
// Azure Storage resource name
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
if (!accountName) throw Error("Azure Storage accountName not found");
// Azure Storage resource key
const accountKey = process.env.AZURE_STORAGE_ACCOUNT_KEY;
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`;
const blobName = `my-blob`;
// Create ContainerClient
const containerClient = new ContainerClient(
`${baseUrl}/${containerName}`,
sharedKeyCredential
);
async function main() {
try {
// Create BlobClient object
const blobClient = containerClient.getBlobClient(blobName);
// do something with blobClient...
const properties = await blobClient.getProperties();
console.log(`Blob ${blobName} properties:`);
// get BlockBlobClient from blobClient
const blockBlobClient = blobClient.getBlockBlobClient();
// do something with blockBlobClient...
const downloadResponse = await blockBlobClient.download(0);
} catch (err) {
console.log(err);
throw err;
}
}
main()
.then(() => console.log(`done`))
.catch((ex) => console.log(ex.message));
直接创建 BlobClient
// Azure Storage dependency
const { BlockBlobClient } = require("@azure/storage-blob");
// Azure authentication for credential dependency
const { DefaultAzureCredential } = require('@azure/identity');
// For development environment - include environment variables from .env
require("dotenv").config();
// Azure Storage resource name
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
if (!accountName) throw Error("Azure Storage accountName not found");
// Azure SDK needs base URL
const baseUrl = `https://${accountName}.blob.core.chinacloudapi.cn`;
// Container must exist prior to running this script
const containerName = `test`;
// Random blob name and contents
const timeStamp = Date.now();
const blobName = `${timeStamp}-my-blob.txt`;
const fileContentsAsString = "Hello there.";
async function main(){
// Create a client that can authenticate with Azure Active Directory
const client = new BlockBlobClient(
`${baseUrl}/${containerName}/${blobName}`,
new DefaultAzureCredential()
);
// Get file url - available before contents are uploaded
console.log(`blob.url: ${client.url}`);
// Upload file contents
const result = await client.upload(fileContentsAsString, fileContentsAsString.length);
// Get results
return result;
}
main().then((result) => console.log(result)).catch((ex) => console.log(ex.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
}
*/
dotenv
包用于从 .env
文件中读取存储帐户名称。 不应将此文件签入到源代码管理中。