使用 .NET 來管理 Azure Data Lake Storage 中的目錄和檔案
此文章說明如何使用 .NET,在具有階層命名空間的儲存體帳戶中建立及管理目錄和檔案。
若要瞭解如何取得、設定及更新目錄和檔案的訪問控制清單(ACL),請參閱 使用 .NET 來管理 Azure Data Lake Storage 中的 ACL。
套件 (NuGet) | 範例 | API 參考 | Gen1 對 Gen2 對應 | 提供意見反應
必要條件
Azure 訂用帳戶。 請參閱取得 Azure 免費試用。
已啟用階層命名空間的儲存體帳戶。 遵循下列指示以建立帳戶。
設定您的專案
若要開始使用,請安裝 Azure.Storage.Files.DataLake NuGet 套件。
如需如何安裝 NuGet 套件的詳細資訊,請參閱使用 NuGet 套件管理員在 Visual Studio 中安裝和管理套件。
然後,使用陳述式在程式碼檔案頂端加入下列命令。
using Azure;
using Azure.Storage.Files.DataLake;
using Azure.Storage.Files.DataLake.Models;
using Azure.Storage;
using System.IO;
注意
Data Lake Storage 上的多重通訊協定存取可讓應用程式同時使用 Blob API 和 Data Lake Storage Gen2 API,以使用已啟用階層命名空間 (HNS) 的記憶體帳戶中的數據。 使用 Data Lake Storage Gen2 特有的功能時,例如目錄作業和 ACL,請使用 Data Lake Storage Gen2 API,如本文所示。
選擇要在指定案例中使用的 API 時,請考慮應用程式的工作負載和需求,以及 HNS 對工作負載和應用程式的已知問題和影響。
授權存取權並連線到資料資源
若要使用此文章中的程式碼範例,您必須建立代表儲存體帳戶的已授權 DataLakeServiceClient 執行個體。 您可以使用 Microsoft Entra ID、帳戶存取密鑰或共用存取簽章 (SAS) 來授權 DataLakeServiceClient
物件。
您可以使用適用於 .NET 的 Azure 身分識別用戶端程式庫,以 Microsoft Entra ID 驗證應用程式。
建立 DataLakeServiceClient 執行個體,並傳入 DefaultAzureCredential 類別的新執行個體。
public static DataLakeServiceClient GetDataLakeServiceClient(string accountName)
{
string dfsUri = $"https://{accountName}.dfs.core.windows.net";
DataLakeServiceClient dataLakeServiceClient = new DataLakeServiceClient(
new Uri(dfsUri),
new DefaultAzureCredential());
return dataLakeServiceClient;
}
若要深入了解如何使用 DefaultAzureCredential
來授權存取資料,請參閱如何向 Azure 服務驗證 .NET 應用程式。
建立容器
容器可作為您檔案的檔案系統。 您可以使用下列方法建立容器:
下列程式碼範例會建立容器,並傳回 DataLakeFileSystemClient 物件以供稍後使用:
public async Task<DataLakeFileSystemClient> CreateFileSystem(
DataLakeServiceClient serviceClient,
string fileSystemName)
{
return await serviceClient.CreateFileSystemAsync(fileSystemName);
}
建立目錄
您可以使用下列方法在容器中建立目錄參考:
下列程式碼範例將目錄新增至容器,接著新增子目錄並傳回 DataLakeDirectoryClient 物件以供稍後使用:
public async Task<DataLakeDirectoryClient> CreateDirectory(
DataLakeFileSystemClient fileSystemClient,
string directoryName,
string subdirectoryName)
{
DataLakeDirectoryClient directoryClient =
await fileSystemClient.CreateDirectoryAsync(directoryName);
return await directoryClient.CreateSubDirectoryAsync(subdirectoryName);
}
重新命名目錄或移動目錄
您可以使用下列方法來重新命名或移動目錄:
將所需目錄的路徑作為參數傳遞。 下列程式碼範例示範如何重新命名子目錄:
public async Task<DataLakeDirectoryClient> RenameDirectory(
DataLakeFileSystemClient fileSystemClient,
string directoryPath,
string subdirectoryName,
string subdirectoryNameNew)
{
DataLakeDirectoryClient directoryClient =
fileSystemClient.GetDirectoryClient(string.Join('/', directoryPath, subdirectoryName));
return await directoryClient.RenameAsync(string.Join('/', directoryPath, subdirectoryNameNew));
}
下列程式碼範例示範如何將子目錄從一個目錄移至另一個目錄:
public async Task<DataLakeDirectoryClient> MoveDirectory(
DataLakeFileSystemClient fileSystemClient,
string directoryPathFrom,
string directoryPathTo,
string subdirectoryName)
{
DataLakeDirectoryClient directoryClient =
fileSystemClient.GetDirectoryClient(string.Join('/', directoryPathFrom, subdirectoryName));
return await directoryClient.RenameAsync(string.Join('/', directoryPathTo, subdirectoryName));
}
將檔案上傳至目錄
您可以使用下列方法將內容上傳至現有或新的檔案:
下列程式碼範例示範如何使用 UploadAsync
方法將本機檔案上傳至目錄:
public async Task UploadFile(
DataLakeDirectoryClient directoryClient,
string fileName,
string localPath)
{
DataLakeFileClient fileClient =
directoryClient.GetFileClient(fileName);
FileStream fileStream = File.OpenRead(localPath);
DataLakeFileUploadOptions uploadOptions = new()
{
// If change notifications are enabled, set Close to true
// This value indicates the final close of the file stream
// And emits a change notification event upon successful flush
// Close = true
};
await fileClient.UploadAsync(content: fileStream, options: uploadOptions);
}
將資料附加至檔案
您可以使用下列方法將資料上傳附加至檔案:
下列程式碼範例示範如何使用以下步驟將資料附加至檔案結尾處:
- 建立 DataLakeFileClient 物件來代表您正在使用的檔案資源。
- 使用 DataLakeFileClient.AppendAsync 方法將資料上傳至檔案。
- 呼叫 DataLakeFileClient.FlushAsync 方法來完成上傳,以將先前上傳的資料寫入檔案。
public async Task AppendDataToFile(
DataLakeDirectoryClient directoryClient,
string fileName,
Stream stream)
{
DataLakeFileClient fileClient =
directoryClient.GetFileClient(fileName);
long fileSize = fileClient.GetProperties().Value.ContentLength;
await fileClient.AppendAsync(stream, offset: fileSize);
DataLakeFileFlushOptions flushOptions = new()
{
// If change notifications are enabled, set Close to true
// This value indicates the final close of the file stream
// And emits a change notification event upon successful flush
// Close = true
};
await fileClient.FlushAsync(position: fileSize + stream.Length, options: flushOptions);
}
從目錄下載
下列程式碼範例示範如何使用以下步驟將檔案從目錄下載至本機檔案:
- 建立 DataLakeFileClient 執行個體,代表您要下載的檔案。
- 使用 DataLakeFileClient.ReadStreamingAsync 方法,然後剖析傳回值以取得 Stream 物件。 使用任何 .NET 檔案處理 API,將資料流中的位元組儲存至檔案。
此範例會使用 BinaryReader 和 FileStream 將位元組儲存至檔案。
public async Task DownloadFile(
DataLakeDirectoryClient directoryClient,
string fileName,
string localPath)
{
DataLakeFileClient fileClient =
directoryClient.GetFileClient(fileName);
Response<DataLakeFileReadStreamingResult> downloadResponse = await fileClient.ReadStreamingAsync();
BinaryReader reader = new BinaryReader(downloadResponse.Value.Content);
FileStream fileStream = File.OpenWrite(localPath);
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
int count;
while ((count = reader.Read(buffer, 0, buffer.Length)) != 0)
{
fileStream.Write(buffer, 0, count);
}
await fileStream.FlushAsync();
fileStream.Close();
}
列出目錄內容
您可以使用下列方法列出目錄內容並列舉結果:
列舉結果中的路徑可能會在擷取值時產生多個要求。
下列程式碼範例會列印位於目錄中的每個檔案名稱:
public async Task ListFilesInDirectory(
DataLakeFileSystemClient fileSystemClient,
string directoryName)
{
IAsyncEnumerator<PathItem> enumerator =
fileSystemClient.GetPathsAsync(directoryName).GetAsyncEnumerator();
await enumerator.MoveNextAsync();
PathItem item = enumerator.Current;
while (item != null)
{
Console.WriteLine(item.Name);
if (!await enumerator.MoveNextAsync())
{
break;
}
item = enumerator.Current;
}
}
刪除目錄
您可以使用下列方法刪除目錄:
下列程式碼範例示範如何刪除目錄:
public async Task DeleteDirectory(
DataLakeFileSystemClient fileSystemClient,
string directoryName)
{
DataLakeDirectoryClient directoryClient =
fileSystemClient.GetDirectoryClient(directoryName);
await directoryClient.DeleteAsync();
}
還原虛刪除的目錄
您可以使用 Azure 儲存體用戶端程式庫來還原虛刪除的目錄。 使用下列方法來列出 DataLakeFileSystemClient 執行個體的已刪除路徑:
使用下列方法來還原虛刪除的目錄:
下列程式碼範例示範如何列出已刪除的路徑並還原虛刪除的目錄:
public async Task RestoreDirectory(
DataLakeFileSystemClient fileSystemClient,
string directoryName)
{
DataLakeDirectoryClient directoryClient =
fileSystemClient.GetDirectoryClient(directoryName);
// List deleted paths
List<PathDeletedItem> deletedItems = new List<PathDeletedItem>();
await foreach (PathDeletedItem deletedItem in fileSystemClient.GetDeletedPathsAsync(directoryName))
{
deletedItems.Add(deletedItem);
}
// Restore deleted directory
Response<DataLakePathClient> restoreResponse = await fileSystemClient.UndeletePathAsync(
deletedItems[0].Path,
deletedItems[0].DeletionId);
}
如果您重新命名包含虛刪除項目的目錄,這些項目就會與目錄中斷連接。 如果您想要還原這些項目,您必須將目錄的名稱還原回其原始名稱,或建立使用原始目錄名稱的不同目錄。 否則,當您嘗試還原這些虛刪除的項目時,將會收到錯誤。
建立目錄的使用者委派 SAS
若要使用本節中的程式碼範例,請新增下列 using
指示詞:
using Azure.Storage.Sas;
下列程式碼範例示範如何在針對儲存體帳戶啟用階層命名空間時,產生目錄的使用者委派 SAS:
async static Task<Uri> GetUserDelegationSasDirectory(DataLakeDirectoryClient directoryClient)
{
try
{
// Get service endpoint from the directory URI.
DataLakeUriBuilder dataLakeServiceUri = new DataLakeUriBuilder(directoryClient.Uri)
{
FileSystemName = null,
DirectoryOrFilePath = null
};
// Get service client.
DataLakeServiceClient dataLakeServiceClient =
new DataLakeServiceClient(dataLakeServiceUri.ToUri(),
new DefaultAzureCredential());
// Get a user delegation key that's valid for seven days.
// You can use the key to generate any number of shared access signatures
// over the lifetime of the key.
Azure.Storage.Files.DataLake.Models.UserDelegationKey userDelegationKey =
await dataLakeServiceClient.GetUserDelegationKeyAsync(DateTimeOffset.UtcNow,
DateTimeOffset.UtcNow.AddDays(7));
// Create a SAS token that's valid for seven days.
DataLakeSasBuilder sasBuilder = new DataLakeSasBuilder()
{
// Specify the file system name and path, and indicate that
// the client object points to a directory.
FileSystemName = directoryClient.FileSystemName,
Resource = "d",
IsDirectory = true,
Path = directoryClient.Path,
ExpiresOn = DateTimeOffset.UtcNow.AddDays(7)
};
// Specify racwl permissions for the SAS.
sasBuilder.SetPermissions(
DataLakeSasPermissions.Read |
DataLakeSasPermissions.Add |
DataLakeSasPermissions.Create |
DataLakeSasPermissions.Write |
DataLakeSasPermissions.List
);
// Construct the full URI, including the SAS token.
DataLakeUriBuilder fullUri = new DataLakeUriBuilder(directoryClient.Uri)
{
Sas = sasBuilder.ToSasQueryParameters(userDelegationKey,
dataLakeServiceClient.AccountName)
};
Console.WriteLine("Directory user delegation SAS URI: {0}", fullUri);
Console.WriteLine();
return fullUri.ToUri();
}
catch (Exception e)
{
Console.WriteLine(e.Message);
throw;
}
}
下列範例會測試從模擬用戶端應用程式在上一個範例中建立的使用者委派 SAS。 如果 SAS 有效,用戶端應用程式就可以列出此目錄的檔案路徑。 如果 SAS 無效 (例如 SAS 已過期),儲存體服務會傳回錯誤碼 403 (禁止)。
private static async Task ListFilesPathsWithDirectorySasAsync(Uri sasUri)
{
// Try performing an operation using the directory SAS provided.
// Create a directory client object for listing operations.
DataLakeDirectoryClient dataLakeDirectoryClient = new DataLakeDirectoryClient(sasUri);
// List file paths in the directory.
try
{
// Call the listing operation and return pages of the specified size.
var resultSegment = dataLakeDirectoryClient.GetPathsAsync(false, false).AsPages();
// Enumerate the file paths returned with each page.
await foreach (Page<PathItem> pathPage in resultSegment)
{
foreach (PathItem pathItem in pathPage.Values)
{
Console.WriteLine("File name: {0}", pathItem.Name);
}
Console.WriteLine();
}
Console.WriteLine();
Console.WriteLine("Directory listing operation succeeded for SAS {0}", sasUri);
}
catch (RequestFailedException e)
{
// Check for a 403 (Forbidden) error. If the SAS is invalid,
// Azure Storage returns this error.
if (e.Status == 403)
{
Console.WriteLine("Directory listing operation failed for SAS {0}", sasUri);
Console.WriteLine("Additional error information: " + e.Message);
Console.WriteLine();
}
else
{
Console.WriteLine(e.Message);
Console.ReadLine();
throw;
}
}
}
若要深入了解如何建立使用者委派 SAS,請參閱使用 .NET 建立使用者委派 SAS。
建立目錄的服務 SAS
在啟用階層命名空間的儲存體帳戶中,您可以建立目錄的服務 SAS。 若要建立服務 SAS,請確定您已安裝 12.5.0 版或更新版本的 Azure.Storage.Files.DataLake 套件。
下列範例示範如何建立目錄的服務 SAS:
private static Uri GetServiceSasUriForDirectory(DataLakeDirectoryClient directoryClient,
string storedPolicyName = null)
{
if (directoryClient.CanGenerateSasUri)
{
// Create a SAS token that's valid for one hour.
DataLakeSasBuilder sasBuilder = new DataLakeSasBuilder()
{
// Specify the file system name, the path, and indicate that
// the client object points to a directory.
FileSystemName = directoryClient.FileSystemName,
Resource = "d",
IsDirectory = true,
Path = directoryClient.Path,
};
// If no stored access policy is specified, create the policy
// by specifying expiry and permissions.
if (storedPolicyName == null)
{
sasBuilder.ExpiresOn = DateTimeOffset.UtcNow.AddHours(1);
sasBuilder.SetPermissions(DataLakeSasPermissions.Read |
DataLakeSasPermissions.Write |
DataLakeSasPermissions.List);
}
else
{
sasBuilder.Identifier = storedPolicyName;
}
// Get the SAS URI for the specified directory.
Uri sasUri = directoryClient.GenerateSasUri(sasBuilder);
Console.WriteLine("SAS URI for ADLS directory is: {0}", sasUri);
Console.WriteLine();
return sasUri;
}
else
{
Console.WriteLine(@"DataLakeDirectoryClient must be authorized with Shared Key
credentials to create a service SAS.");
return null;
}
}
若要深入了解如何建立服務 SAS,請參閱使用 .NET 建立服務 SAS。