Leer en inglés

Compartir a través de

使用 .NET 针对 Azure 文件进行开发

了解如何开发使用 Azure 文件存储数据的 .NET 应用程序。 Azure 文件是云中的托管文件共享服务。 它提供可通过行业标准服务器消息块(SMB)和网络文件系统(NFS)协议访问的完全托管文件共享。 Azure 文件存储还提供 REST API,用于以编程方式访问文件共享。

在本文中,你将了解使用 .NET 中的 Azure 文件开发的不同方法,以及如何选择最适合应用需求的方法。 你还将了解如何创建与 Azure 文件资源交互的基本控制台应用。

适用于

管理模型 计费模式 媒体层 冗余 中小型企业 (SMB) 网络文件系统(NFS)
Microsoft.Storage 预配版本 v1 SSD(高级) 本地 (LRS) Yes No
Microsoft.Storage 预配版本 v1 SSD(高级) 区域 (ZRS) Yes No
Microsoft.Storage 即用即付 HDD(标准) 本地 (LRS) Yes No
Microsoft.Storage 即用即付 HDD(标准) 区域 (ZRS) Yes No
Microsoft.Storage 即用即付 HDD(标准) 异地 (GRS) Yes No
Microsoft.Storage 即用即付 HDD(标准) GeoZone (GZRS) Yes No

关于使用 Azure 文件进行 .NET 应用开发

Azure 文件存储为 .NET 开发人员提供了多种方式来访问数据和管理 Azure 文件存储中的资源。 下表列出了这些方法,总结了它们的工作方式,并提供有关何时使用每个方法的指导:

方法 工作原理 何时使用
标准文件 I/O 库 通过使用 SMB 或 NFS 装载的 Azure 文件共享使用 OS 级 API 调用。 使用 SMB/NFS 装载文件共享时,可以将文件 I/O 库用于编程语言或框架,例如 System.IO 用于 .NET。 你拥有已有代码使用标准文件 I/O 的业务线应用,并且不希望重写代码来让应用程序可以与 Azure 文件共享一起使用。
FileREST API 直接调用 HTTPS 终结点以与存储在 Azure 文件中的数据进行交互。 提供对文件共享资源的编程控制。 Azure SDK 提供基于 FileREST API 构建的文件共享客户端库(Azure.Storage.Files.Shares),允许你通过熟悉的 .NET 编程语言范例与 FileREST API作进行交互。 你要为客户构建增值云服务和应用,并且想要使用无法通过 System.IO的高级功能。
存储资源提供程序 REST API 使用 Azure 资源管理器(ARM)管理存储帐户和文件共享。 为了进行各种资源管理操作,调用REST API终结点。 应用或服务需要执行资源管理任务,例如创建、删除或更新存储帐户或文件共享。

有关这些方法的一般信息,请参阅 Azure 文件存储的应用程序开发概述

本文重点介绍如何使用以下方法使用 Azure 文件资源:

先决条件

配置你的环境

本部分逐步讲解如何准备 .NET 控制台应用以使用 Azure 文件。

创建项目

如果还没有 .NET 应用,请使用 Visual Studio 或 .NET CLI 创建一个。 在本文中,我们将创建一个控制台应用,以便于简单。

  1. 启动 Visual Studio 并选择“创建新项目”。 或者,如果你在 Visual Studio 中,请导航到 “文件>新建>项目”。
  2. 在对话框窗口中,选择适用于 C# 的 控制台应用 ,然后选择“ 下一步”。
  3. 输入项目的名称,保留默认值,然后选择“ 下一步”。
  4. 对于 Framework,请选择最新版本的 .NET。 保留其他默认值,然后选择“ 创建”。

安装软件包

如果计划使用 System.IO 命名空间与 Azure 文件进行交互,则无需安装任何其他包。 命名空间 System.IO 包含在 .NET SDK 中。 如果计划使用适用于 .NET 的文件共享客户端库或适用于 .NET 的 Azure 存储管理库,请使用 NuGet 安装包。

  1. 在“解决方案资源管理器”中,右键单击你的项目并选择“管理 NuGet 包” 。

  2. 在“NuGet 包管理器”中选择“浏览”。 然后搜索并选择相应的包,然后选择“ 安装”。 对于文件共享客户端库,请选择 “Azure.Storage.Files.Shares”。 对于 Azure 存储管理库,请选择 Azure.ResourceManager.Storage。 对于无密码连接所需的 Azure 标识库,请选择 Azure.Identity

    此步骤将安装该包及其依赖项。

添加 using 指令

如果打算使用 System.IO 命名空间,请将以下 using 指令添加到 Program.cs 文件的顶部:

using System.IO;

如果打算使用适用于 .NET 的文件共享客户端库,请将以下 using 指令添加到 Program.cs 文件的顶部:

using Azure.Storage.Files.Shares;

如果计划使用适用于 .NET 的 Azure 存储管理库,请将以下 using 指令添加到 Program.cs 文件的顶部:

using Azure.ResourceManager;

若要将 Azure 标识库用于与 Azure 服务的无密码连接,请将以下 using 指令添加到 Program.cs 文件的顶部:

using Azure.Identity;

使用 System.IO 处理 Azure 文件

标准文件 I/O 库是访问和使用 Azure 文件资源的最常用方法。 使用 SMB 或 NFS 装载文件共享时,操作系统会重定向本地文件系统的 API 请求。 此方法允许你使用标准文件 I/O 库(例如 System.IO,与共享中的文件和目录进行交互)。

考虑在应用需要时使用 System.IO

  • 应用兼容性: 非常适合具有已使用 System.IO的现有代码的业务线应用。 无需为应用重写代码才能使用 Azure 文件共享。
  • 易于使用:System.IO 由开发人员熟知,易于使用。 Azure 文件存储的关键价值主张是通过 SMB 和 NFS 公开本机文件系统 API。

在本部分中,您将学习如何使用 System.IO 与 Azure 文件资源进行操作。

有关详细信息和示例,请参阅以下资源:

装载文件共享

若要使用 System.IO,必须先装载文件共享。 有关如何使用 SMB 或 NFS 装载文件共享的指导,请参阅以下资源:

在本文中,我们将使用以下路径来引用 Windows 上装载的 SMB 文件共享:

string fileSharePath = @"Z:\file-share";

示例:使用 System.IO 连接到文件共享和枚举目录

下面的代码示例演示如何连接到文件共享并列出共享中的目录:

using System.IO;

string fileSharePath = @"Z:\file-share";

EnumerateDirectories(@"Z:\file-share");

static void EnumerateDirectories(string path)
{
    try
    {
        List<string> dirs = new List<string>(Directory.EnumerateDirectories(path));

        foreach (var dir in dirs)
        {
            Console.WriteLine($"{dir.Substring(dir.LastIndexOf(Path.DirectorySeparatorChar) + 1)}");
        }
        Console.WriteLine($"{dirs.Count} directories found.");
    }
    catch (UnauthorizedAccessException ex)
    {
        Console.WriteLine(ex.Message);
    }
    catch (PathTooLongException ex)
    {
        Console.WriteLine(ex.Message);
    }
}

示例:使用 System.IO 写入文件共享中的文件

下面的代码示例演示如何使用 File 类编写和追加文本:

using System.IO;

string fileSharePath = @"Z:\file-share";

WriteToFile(fileSharePath, "test.txt");

static void WriteToFile(string fileSharePath, string fileName)
{
    string textToWrite = "First line" + Environment.NewLine;
    string filePath = Path.Combine(fileSharePath, fileName);
    
    File.WriteAllText(filePath, textToWrite);

    string[] textToAppend = { "Second line", "Third line" };
    File.AppendAllLines(filePath, textToAppend);
}

示例:使用 System.IO 锁定文件共享中的文件

装载文件共享的 SMB 客户端可以使用文件系统锁定机制来管理对共享文件的访问。

下面的代码示例演示如何在文件共享中锁定文件,并将共享模式设置为 None。 此共享模式拒绝共享当前文件,直到文件关闭。

using System.IO;

string fileSharePath = @"Z:\file-share";

LockFile(Path.Combine(fileSharePath, "test.txt"));

static void LockFile(string filePath)
{
    try
    {
        using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
        {
            Console.WriteLine("File locked.");

            // Do something with file, press Enter to close the stream and release the lock
            Console.ReadLine();

            fs.Close();
            Console.WriteLine("File closed.");
        }
    }
    catch (IOException ex)
    {
        Console.WriteLine(ex.Message);
    }
}

同时使用 SMB 和 FileREST API 时,请记住,FileREST API 使用 租约 来管理文件锁,而 SMB 使用由作系统管理的文件系统锁。 若要详细了解如何管理 SMB 与 FileREST API 之间的文件锁定交互,请参阅 管理文件锁

示例:使用 System.IO 枚举文件 ACL

下面的代码示例演示如何枚举文件的访问控制列表(ACL):

using System.IO;
using System.Security.AccessControl;

string fileSharePath = @"Z:\file-share";
string fileName = "test.txt";
string filePath = Path.Combine(fileSharePath, fileName);

EnumerateFileACLs(filePath);

static void EnumerateFileACLs(string filePath)
{
    FileInfo fileInfo = new FileInfo(filePath);

    // For directories, use DirectorySecurity instead of FileSecurity
    FileSecurity fSecurity = FileSystemAclExtensions.GetAccessControl(fileInfo);

    // List all access rules for the file
    foreach (FileSystemAccessRule rule in fSecurity.GetAccessRules(true, true, typeof(System.Security.Principal.NTAccount)))
    {
        Console.WriteLine($"Identity: {rule.IdentityReference.Value}");
        Console.WriteLine($"Access Control Type: {rule.AccessControlType}");
        Console.WriteLine($"File System Rights: {rule.FileSystemRights}");
        Console.WriteLine();
    }

}

使用适用于 .NET 的文件共享客户端库处理 Azure 文件存储数据

FileREST API 提供对 Azure 文件的编程访问。 它允许调用 HTTPS 端点来对文件共享、目录和文件执行操作。 FileREST API 旨在实现高可伸缩性和高级功能,这些功能可能无法通过本机协议使用。 Azure SDK 提供基于 FileREST API 生成的客户端库(例如用于 .NET 的文件共享客户端库)。

如果应用程序需要,请考虑使用 FileREST API 和文件共享客户端库:

  • 高级功能: 访问无法通过原生协议获得的操作和功能。
  • 自定义云集成: 生成与 Azure 文件直接交互的自定义增值服务,例如备份、防病毒或数据管理。
  • 性能优化: 在大规模场景中,通过数据平面操作享受性能优势。

FileREST API 将 Azure 文件建模为资源层次结构,建议用于在 目录文件 级别执行的作。 对于在文件服务文件共享级别执行的作,应首选存储资源提供程序 REST API

本部分介绍如何使用文件共享客户端库处理 Azure 文件资源。

有关详细信息和示例,请参阅以下资源:

授予访问权限并创建客户端

若要将应用连接到 Azure 文件存储,请创建一个 ShareClient 对象。 此对象是开始与 Azure 文件资源进行工作的起点。 以下代码示例演示如何使用不同的授权机制创建 ShareClient 对象。

若要使用 Microsoft Entra ID 进行授权,需要使用安全主体。 你需要的安全主体的类型取决于你的应用在哪里运行。 使用此表作为指南。

应用的运行位置 安全主体 指南
本地计算机(开发和测试) 服务主体 若要了解如何注册应用、设置 Microsoft Entra 组、分配角色和配置环境变量,请参阅使用开发人员服务主体授权访问
本地计算机(开发和测试) 用户标识 若要了解如何设置 Microsoft Entra 组、分配角色和登录到 Azure,请参阅使用开发人员凭据授权访问
在 Azure 中托管 托管标识 若要了解如何启用托管标识和分配角色,请参阅使用托管标识授权从 Azure 托管应用访问
托管在 Azure 外部(例如本地应用) 服务主体 若要了解如何注册应用、分配角色和配置环境变量,请参阅使用应用程序服务主体授权从本地应用访问

若要使用本文中的代码示例,请将 Azure RBAC 内置角色 存储文件数据特权参与者 分配给安全主体。 此角色对所有已配置存储帐户的共享中的所有数据具有完全读取、写入、修改 ACL、删除访问权限,而不考虑设置的文件/目录级别 NTFS 权限。 有关详细信息,请参阅 通过 REST 通过 Azure 文件 OAuth 使用 Microsoft Entra ID 访问 Azure 文件共享

使用 DefaultAzureCredential 授权访问

授权访问和连接到 Azure 文件的简单安全方法是通过创建 DefaultAzureCredential 实例来获取 OAuth 令牌。 然后,你可以使用该凭据创建 ShareClient 对象。

以下示例创建一个 ShareClient 使用 DefaultAzureCredential授权的对象,然后创建一个 ShareDirectoryClient 对象来处理共享中的目录:

using Azure.Identity;
using Azure.Storage.Files.Shares;
using Azure.Storage.Files.Shares.Models;

// ...

string accountName = "<account-name>";
string shareName = "<share-name>";

ShareClientOptions options = new()
{
    AllowSourceTrailingDot = true,
    AllowTrailingDot = true,
    ShareTokenIntent = ShareTokenIntent.Backup,
};
ShareClient shareClient = new(
   new Uri($"https://{accountName}.file.core.chinacloudapi.cn/{shareName}"),
   new DefaultAzureCredential(),
   options);

ShareDirectoryClient directoryClient = shareClient.GetDirectoryClient("sample-directory");

如果你准确地知道将用于对用户进行身份验证的凭据类型,可以使用适用于 .NET 的 Azure 标识客户端库中的其他类获取 OAuth 令牌。 这些类派生自 TokenCredential 类。

若要详细了解每种授权机制,请参阅 “选择如何授权访问文件数据”。

示例:使用文件共享客户端库复制文件

可以使用以下方法在文件共享内或文件共享之间复制文件:

可使用 BlobClient 对象中的以下方法将文件复制到目标 Blob:

下面的代码示例演示如何将文件复制到另一个文件共享中的文件:

using Azure.Core;
using Azure.Identity;
using Azure.Storage.Files.Shares;
using Azure.Storage.Files.Shares.Models;

string accountName = "<account-name>";
string srcShareName = "src-file-share";
string destShareName = "dest-file-share";
string srcFilePath = "src/path/to/file";
string destFilePath = "dest/path/to/file";

TokenCredential tokenCredential = new DefaultAzureCredential();

ShareClientOptions options = new()
{
    ShareTokenIntent = ShareTokenIntent.Backup,
};

ShareFileClient srcShareFileClient = new(
    new Uri($"https://{accountName}.file.core.chinacloudapi.cn/{srcShareName}/{srcFilePath}"),
    tokenCredential,
    options);

ShareFileClient destShareFileClient = new(
    new Uri($"https://{accountName}.file.core.chinacloudapi.cn/{destShareName}/{destFilePath}"),
    tokenCredential,
    options);

// Copy the file from the source share to the destination share

await destShareFileClient.StartCopyAsync(srcShareFileClient.Uri);

示例:使用文件共享客户端库租用文件

租约通过租约 ID 在 Azure 管理的文件上创建锁。 租约提供了一种机制,用于协调对分布式系统中多个客户端的文件的访问。 文件的租约提供独占写入和删除访问权限。 若要详细了解租约状态和作,请参阅 租约文件

下面的代码示例演示如何创建租约客户端、获取文件的无限持续时间租约以及释放租约:

using Azure.Core;
using Azure.Identity;
using Azure.Storage.Files.Shares;
using Azure.Storage.Files.Shares.Models;
using Azure.Storage.Files.Shares.Specialized;

string accountName = "<account-name>";
string shareName = "sample-file-share";
string filePath = "path/to/file";

TokenCredential tokenCredential = new DefaultAzureCredential();

ShareClientOptions options = new()
{
    ShareTokenIntent = ShareTokenIntent.Backup,
};

ShareFileClient fileClient = new(
    new Uri($"https://{accountName}.file.core.chinacloudapi.cn/{shareName}/{filePath}"),
    tokenCredential,
    options);

ShareLeaseClient leaseClient = fileClient.GetShareLeaseClient();

// Acquire a lease on the source file
await leaseClient.AcquireAsync(duration: ShareLeaseClient.InfiniteLeaseDuration);

// Do something with the file

// Release the lease
await leaseClient.ReleaseAsync();

同时使用 SMB 和 FileREST API 时,请记住,FileREST API 使用 租约 来管理文件锁,而 SMB 使用由作系统管理的文件系统锁。 若要详细了解如何管理 SMB 与 FileREST API 之间的文件锁定交互,请参阅 管理文件锁

示例:使用文件共享客户端库创建和列出共享快照

共享快照是某个时间点文件共享的只读副本。 可以创建文件共享的快照,然后在创建快照时使用快照访问共享中的数据。 还可以列出文件共享中的所有快照,并删除共享快照。

以下代码示例演示如何创建共享快照、列出文件共享中的快照,以及遍历共享快照中的目录树:

using Azure.Storage.Files.Shares;
using Azure.Storage.Files.Shares.Models;

string connectionString = "<connection-string>";

ShareServiceClient shareServiceClient = new ShareServiceClient(connectionString);
ShareClient shareClient = shareServiceClient.GetShareClient("sample-file-share");

// Create a snapshot

ShareSnapshotInfo snapshotInfo = await shareClient.CreateSnapshotAsync();
Console.WriteLine($"Snapshot created: {snapshotInfo.Snapshot}");

// List snapshots in a share

await foreach (ShareItem shareItem in shareServiceClient.GetSharesAsync(ShareTraits.All, ShareStates.Snapshots))
{
    if (shareItem.Snapshot != null)
    {
        Console.WriteLine($"Share: {shareItem.Name} (Snapshot: {shareItem.Snapshot})");
    }
}

// List directories and files in a share snapshot

string snapshotTimestamp = snapshotInfo.Snapshot.ToString();
ShareClient shareSnapshot = shareClient.WithSnapshot(snapshotTimestamp);
ShareDirectoryClient rootDir = shareSnapshot.GetRootDirectoryClient();

await ListDirectoryTreeAsync(rootDir);

static async Task ListDirectoryTreeAsync(ShareDirectoryClient directory)
{
    await foreach (ShareFileItem fileItem in directory.GetFilesAndDirectoriesAsync())
    {
        if (fileItem.IsDirectory)
        {
            Console.WriteLine($"Directory: {fileItem.Name}");
            await ListDirectoryTreeAsync(directory.GetSubdirectoryClient(fileItem.Name));
        }
        else
        {
            Console.WriteLine($"File: {fileItem.Name}");
        }
    }
}

Nota

不允许在文件共享级别的数据平面操作中使用 OAuth 令牌,例如那些在使用 DefaultAzureCredential 时获取的令牌。 若要使用共享快照,必须使用帐户密钥对客户端对象进行授权。 ShareClient在此代码示例中创建的对象使用连接字符串,其中包括帐户密钥。

存储帐户密钥或连接字符串会带来安全风险。 仅当Microsoft Entra 身份验证不可用时,才应使用它们。 若要详细了解如何在 Azure Key Vault 中安全地存储帐户密钥,请参阅 关于 Azure Key Vault 托管存储帐户密钥

使用 Azure 存储管理库管理 Azure 文件资源

Azure 存储管理库基于 Azure 存储资源提供程序 REST API 构建。 Azure 存储资源提供程序是基于 Azure 资源管理器的服务,支持声明性(模板)和命令性(直接 API 调用)方法。 Azure 存储资源提供程序 REST API 提供对 Azure 存储资源的编程访问,包括文件共享。 Azure SDK 提供基于 Azure 存储资源提供程序 REST API 构建的管理库。

对于在 文件服务文件共享 级别执行的作,建议使用管理库。 本部分介绍如何使用 Azure 存储管理库管理 Azure 文件资源。

示例:使用 Azure 存储管理库创建文件共享

以下代码示例演示如何创建顶级 ArmClient 对象、向订阅注册存储资源提供程序,以及如何使用 Azure 存储管理库创建文件共享:

using Azure;
using Azure.Core;
using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.Resources;
using Azure.ResourceManager.Storage;

ArmClient armClient = new ArmClient(new DefaultAzureCredential(), new ArmClientOptions { Environment = ArmEnvironment.AzureChina });

// Create a resource identifier, then get the subscription resource
ResourceIdentifier resourceIdentifier = new($"/subscriptions/<subscription-id>");
SubscriptionResource subscription = armClient.GetSubscriptionResource(resourceIdentifier);

ResourceProviderResource resourceProvider =
    await subscription.GetResourceProviderAsync("Microsoft.Storage");

// Check the registration state of the resource provider and register, if needed
if (resourceProvider.Data.RegistrationState == "NotRegistered")
    resourceProvider.Register();

// Get a resource group
ResourceGroupResource resourceGroup = await subscription.GetResourceGroupAsync("<resource-group-name>");

// Get a collection of storage account resources
StorageAccountCollection accountCollection = resourceGroup.GetStorageAccounts();

// Get a specific storage account resource
StorageAccountResource storageAccount = await accountCollection.GetAsync("<storage-account-name>");

// Get a file service resource for the storage account
FileServiceResource fileService = storageAccount.GetFileService();

// Create a new file share (or update if it already exists)
ArmOperation <FileShareResource> fileShareOperation = await fileService
    .GetFileShares()
    .CreateOrUpdateAsync(WaitUntil.Completed, "sample-file-share", new FileShareData()
    {
        ShareQuota = 1024,
        // Add file share properties here
    });

// Get the file share resource
FileShareResource fileShare = fileShareOperation.Value;

可以使用 FileShareData 类配置文件共享属性。 上一个示例演示如何设置 ShareQuota 属性。

Nota

若要执行注册操作,需要以下 Azure RBAC 操作的权限:Microsoft.Storage/register/action。 此权限包含在参与者和所有者内置角色中。

示例:使用 Azure 存储管理库列出文件共享和快照

以下代码示例演示如何列出存储帐户中的文件共享和快照:

// Iterate over a collection of file shares and list them along with any snapshots
string expand = "snapshots";
await foreach (FileShareResource shareResource in fileService.GetFileShares().GetAllAsync(expand: expand))
{
    // Call operations on the file share resource

    // For this demo, print out the resource name and snapshot information
    FileShareData resourceData = shareResource.Data;
    Console.WriteLine($"Resource name: {resourceData.Name}");
    if (resourceData.SnapshotOn.HasValue)
    {
        Console.WriteLine($"Snapshot: {resourceData.SnapshotOn}");
    }
}

有关使用 Azure 文件进行开发的详细信息,请参阅以下资源: