Verwenden von .NET zum Verwalten von Verzeichnissen und Dateien in Azure Data Lake Storage Gen2

In diesem Artikel erfahren Sie, wie Sie mithilfe von .NET Verzeichnisse und Dateien in Speicherkonten erstellen und verwalten, die über einen hierarchischen Namespace verfügen.

Informationen zum Abrufen, Festlegen und Aktualisieren der Zugriffssteuerungslisten (Access Control Lists, ACLs) von Verzeichnissen und Dateien finden Sie unter Verwenden von .NET zum Verwalten von Zugriffssteuerungslisten in Azure Data Lake Storage Gen2.

NuGet-Paket | Beispiele | API-Referenz | Zuordnung von Gen1 zu Gen2 | Feedback geben

Voraussetzungen

Einrichten des Projekts

Installieren Sie zunächst das NuGet-Paket Azure.Storage.Files.DataLake.

Weitere Informationen zum Installieren von NuGet-Paketen finden Sie unter Installieren und Verwalten von Paketen in Visual Studio mit dem NuGet-Paket-Manager.

Fügen Sie dann die folgenden using-Anweisungen am Anfang Ihrer Codedatei ein.

using Azure;
using Azure.Storage.Files.DataLake;
using Azure.Storage.Files.DataLake.Models;
using Azure.Storage;
using System.IO;

Hinweis

Der Multiprotokollzugriff auf Data Lake Storage ermöglicht Anwendungen die Verwendung von Blob-APIs und Data Lake Storage Gen2-APIs zum Arbeiten mit Daten in Speicherkonten mit aktiviertem hierarchischen Namespace (HNS). Wenn Sie mit speziellen Funktionen für Data Lake Storage Gen2 arbeiten, z. B. Verzeichnisvorgängen und ACLs, verwenden Sie die Data Lake Storage Gen2-APIs, wie in diesem Artikel gezeigt.

Berücksichtigen Sie bei der Auswahl der APIs, die in einem bestimmten Szenario verwendet werden sollen, die Workload und die Anforderungen Ihrer Anwendung sowie die bekannten Probleme und die Auswirkungen eines HNS auf Workloads und Anwendungen.

Autorisieren des Zugriffs und Herstellen einer Verbindung mit Datenressourcen

Um mit den Codebeispielen in diesem Artikel zu arbeiten, müssen Sie eine autorisierte DataLakeServiceClient-Instanz erstellen, die das Speicherkonto darstellt. Sie können ein DataLakeServiceClient-Objekt mithilfe von Microsoft Entra ID, einem Kontozugriffsschlüssels oder einer gemeinsamen Zugriffssignatur (Shared Access Signature, SAS) autorisieren.

Sie können die Azure-Identitätsclientbibliothek für .NET verwenden, um Ihre Anwendung bei Microsoft Entra ID zu authentifizieren.

Erstellen Sie eine DataLakeServiceClient-Instanz und übergeben Sie eine neue Instanz der DefaultAzureCredential-Klasse.

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

Weitere Informationen zur Verwendung von DefaultAzureCredential zum Autorisieren des Datenzugriffs finden Sie unter Authentifizieren von .NET-Anwendungen mit Azure-Diensten.

Erstellen eines Containers

Ein Container fungiert als Dateisystem für Ihre Dateien. Sie können einen Container mittels der folgenden Methode erstellen:

Im folgenden Codebeispiel wird ein Container erstellt und ein DataLakeFileSystemClient-Objekt zur späteren Verwendung zurückgegeben:

public async Task<DataLakeFileSystemClient> CreateFileSystem(
    DataLakeServiceClient serviceClient,
    string fileSystemName)
{
    return await serviceClient.CreateFileSystemAsync(fileSystemName);
}

Erstellen eines Verzeichnisses

Sie können einen Verzeichnisverweis im Container erstellen, indem Sie die folgende Methode verwenden:

Das folgende Codebeispiel fügt einem Container ein Verzeichnis hinzu, fügt dann ein Unterverzeichnis hinzu und gibt ein DataLakeDirectoryClient-Objekt zur späteren Verwendung zurück:

public async Task<DataLakeDirectoryClient> CreateDirectory(
    DataLakeFileSystemClient fileSystemClient,
    string directoryName,
    string subdirectoryName)
{
    DataLakeDirectoryClient directoryClient =
        await fileSystemClient.CreateDirectoryAsync(directoryName);

    return await directoryClient.CreateSubDirectoryAsync(subdirectoryName);
}

Umbenennen oder Verschieben eines Verzeichnisses

Sie können ein Verzeichnis mittels der folgenden Methode umbenennen oder verschieben:

Übergeben Sie den Pfad des gewünschten Verzeichnisses als Parameter. Das folgende Codebeispiel zeigt, wie ein Unterverzeichnis umbenannt wird:

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

Das folgende Codebeispiel zeigt, wie ein Unterverzeichnis aus einem Verzeichnis in ein anderes Verzeichnis verschoben wird:

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

Hochladen einer Datei in ein Verzeichnis

Sie können Inhalte mittels der folgenden Methode in eine neue oder vorhandene Datei hochladen:

Das folgende Codebeispiel zeigt, wie sie mithilfe der UploadAsync-Methode eine lokale Datei in ein Verzeichnis hochladen:

public async Task UploadFile(
    DataLakeDirectoryClient directoryClient,
    string fileName,
    string localPath)
{
    DataLakeFileClient fileClient = 
        directoryClient.GetFileClient(fileName);

    FileStream fileStream = File.OpenRead(localPath);

    await fileClient.UploadAsync(content: fileStream, overwrite: true);
}

Sie können diese Methode verwenden, um Inhalte zu erstellen und in eine neue Datei hochzuladen, oder Sie können den overwrite-Parameter auf true festlegen, um eine vorhandene Datei zu überschreiben.

Anfügen von Daten an eine Datei

Sie können Daten hochladen, die an eine Datei angefügt werden sollen, indem Sie die folgende Methode verwenden:

Das folgende Codebeispiel zeigt, wie Sie mithilfe dieser Schritte Daten an das Ende einer Datei anfügen:

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

    await fileClient.FlushAsync(position: fileSize + stream.Length);
}

Herunterladen aus einem Verzeichnis

Das folgende Codebeispiel zeigt, wie Sie mithilfe dieser Schritte eine Datei aus einem Verzeichnis in eine lokale Datei herunterladen:

  • Erstellen Sie eine DataLakeFileClient-Instanz, um die Datei darzustellen, die Sie herunterladen wollen.
  • Verwenden Sie die DataLakeFileClient.ReadAsync-Methode, und parsen Sie dann den Rückgabewert, um ein Stream-Objekt zu erhalten. Verwenden Sie eine beliebige .NET-API für die Dateiverarbeitung, um Bytes aus dem Datenstrom in einer Datei zu speichern.

Im folgenden Beispiel werden BinaryReader und FileStream verwendet, um Bytes in einer Datei zu speichern.

public async Task DownloadFile(
    DataLakeDirectoryClient directoryClient,
    string fileName,
    string localPath)
{
    DataLakeFileClient fileClient =
        directoryClient.GetFileClient(fileName);

    Response<FileDownloadInfo> downloadResponse = await fileClient.ReadAsync();

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

Auflisten des Verzeichnisinhalts

Sie können Verzeichnisinhalte auflisten, indem Sie die folgende Methode verwenden und das Ergebnis aufzählen:

Beim Aufzählen der Pfade im Ergebnis werden möglicherweise mehrere Anforderungen an den Dienst gestellt, während die Werte abgerufen werden.

Das folgenden Codebeispiel gibt Namen aller Dateien aus, die sich in einem Verzeichnis befinden:

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

}

Löschen eines Verzeichnisses

Sie können ein Verzeichnis mittels der folgenden Methode löschen:

Das folgende Codebeispiel zeigt, wie ein Verzeichnis gelöscht wird:

public async Task DeleteDirectory(
    DataLakeFileSystemClient fileSystemClient,
    string directoryName)
{
    DataLakeDirectoryClient directoryClient =
        fileSystemClient.GetDirectoryClient(directoryName);

    await directoryClient.DeleteAsync();
}

Wiederherstellen eines vorläufig gelöschten Verzeichnisses

Sie können die Azure Storage-Clientbibliotheken zum Wiederherstellen vorläufig gelöschter Verzeichnisse verwenden. Verwenden Sie die folgende Methode, um gelöschte Pfade für eine DataLakeFileSystemClient-Instanz aufzulisten:

Verwenden Sie die folgende Methode, um ein vorläufig gelöschtes Verzeichnis wiederherzustellen:

Das folgende Codebeispiel zeigt, wie Sie gelöschte Pfade auflisten und ein vorläufig gelöschtes Verzeichnis wiederherstellen:

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

Wenn Sie das Verzeichnis umbenennen, das die vorläufig gelöschten Elemente enthält, werden diese Elemente vom Verzeichnis getrennt. Wenn Sie diese Elemente wiederherstellen möchten, müssen Sie den Namen des Verzeichnisses auf seinen ursprünglichen Namen zurücksetzen oder ein separates Verzeichnis erstellen, das den ursprünglichen Verzeichnisnamen verwendet. Andernfalls erhalten Sie einen Fehler, wenn Sie versuchen, diese vorläufig gelöschten Elemente wiederherzustellen.

Erstellen einer SAS für die Benutzerdelegierung für ein Verzeichnis

Um mit den Codebeispielen in diesem Abschnitt zu arbeiten, fügen Sie die folgende using-Direktive hinzu:

using Azure.Storage.Sas;

Im folgenden Codebeispiel wird gezeigt, wie Sie eine SAS für die Benutzerdelegierung für ein Verzeichnis generieren, wenn ein hierarchischer Namespace für das Speicherkonto aktiviert ist:

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

Im folgenden Beispiel wird die im vorherigen Beispiel erstellte SAS für die Benutzerdelegierung in einer simulierten Clientanwendung getestet. Wenn die SAS gültig ist, kann die Clientanwendung Dateipfade in diesem Verzeichnis auflisten. Wenn die SAS ungültig ist (z. B. wenn die SAS abgelaufen ist), gibt der Speicherdienst den Fehlercode 403 (Verboten) zurück.

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

Weitere Informationen zum Erstellen einer SAS für die Benutzerdelegierung finden Sie unter Erstellen einer SAS für die Benutzerdelegierung mit .NET.

Erstellen einer Dienst-SAS für ein Verzeichnis

In einem Speicherkonto mit einem aktivierten hierarchischen Namespace können Sie eine Dienst-SAS für ein Verzeichnis erstellen. Stellen Sie zum Erstellen der Dienst-SAS sicher, dass Sie Version 12.5.0 oder höher des Azure.Storage.Files.DataLake-Pakets installiert haben.

Im folgenden Beispiel wird gezeigt, wie Sie eine Dienst-SAS für ein Verzeichnis erstellen:

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

Weitere Informationen zum Erstellen einer Dienst-SAS finden Sie unter Erstellen einer Dienst-SAS mit .NET.

Weitere Informationen