Utiliser .NET pour gérer les répertoires et les fichiers dans Azure Data Lake Storage Gen2

Cet article explique comment utiliser .NET pour créer et gérer les répertoires et les fichiers dans les comptes de stockage dotés d’un espace de noms hiérarchique.

Pour en savoir plus sur la façon d’obtenir, de définir et de mettre à jour les listes de contrôle d’accès (ACL, Access Control List) des répertoires et des fichiers, consultez Utiliser .NET pour gérer les listes de contrôle d’accès dans Azure Data Lake Storage Gen2.

Package (NuGet) | Exemples | Référence d’API | Mappage de Gen1 à Gen2 | Envoyer des commentaires

Prérequis

Configuration de votre projet

Pour commencer, installez le package NuGet Azure.Storage.Files.DataLake.

Pour plus d’informations sur l’installation des packages NuGet, consultez Installer et gérer des packages dans Visual Studio à l’aide du gestionnaire de package NuGet.

Ensuite, ajoutez les instructions using suivantes au début de votre fichier de code.

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

Remarque

L’accès multiprotocole sur Data Lake Storage permet aux applications d’utiliser à la fois les API Blob et les API Data Lake Storage Gen2 pour travailler avec des données dans des comptes de stockage dont l’espace de noms hiérarchique (HNS) est activé. Lorsque vous travaillez avec des fonctionnalités propres à Data Lake Storage Gen2, telles que les opérations de répertoire et les ACL, utilisez les API de Data Lake Storage Gen2, comme indiqué dans cet article.

Lorsque vous choisissez les API à utiliser dans un scénario donné, tenez compte de la charge de travail et des besoins de votre application, ainsi que des problèmes connus et de l’impact de HNS sur les charges de travail et les applications.

Autoriser l’accès aux ressources de données et se connecter à celles-ci

Pour utiliser les exemples de code de cet article, vous devez créer une instance DataLakeServiceClient autorisée qui représente le compte de stockage. Vous pouvez autoriser un objet DataLakeServiceClient à l'aide de Microsoft Entra ID, d'une clé d'accès au compte ou d'une signature d'accès partagé (SAP).

Vous pouvez utiliser la bibliothèque de client Azure Identity pour .NET afin d’authentifier votre application auprès de Microsoft Entra ID.

Créez une instance DataLakeServiceClient et transmettez une nouvelle instance de la classe 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;
}

Pour en savoir plus sur l’utilisation de DefaultAzureCredential afin d’autoriser l’accès aux données, consultez Comment authentifier des applications .NET auprès des services Azure.

Créez un conteneur.

Un conteneur fait office de système de fichiers pour vos fichiers. Vous pouvez créer un conteneur à l’aide de la méthode suivante :

L’exemple de code suivant crée un conteneur et retourne un objet DataLakeFileSystemClient pour une utilisation ultérieure :

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

Créer un répertoire

Vous pouvez créer une référence de répertoire dans le conteneur à l’aide de la méthode suivante :

L’exemple de code suivant ajoute un répertoire à un conteneur, puis ajoute un sous-répertoire et retourne un objet DataLakeDirectoryClient pour une utilisation ultérieure :

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

    return await directoryClient.CreateSubDirectoryAsync(subdirectoryName);
}

Renommer ou déplacer un répertoire

Vous pouvez renommer ou déplacer un répertoire à l’aide de la méthode suivante :

Transmettez le chemin d’accès au répertoire souhaité en tant que paramètre. L’exemple de code suivant montre comment renommer un sous-répertoire :

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

L’exemple de code suivant montre comment déplacer un sous-répertoire d’un répertoire vers un autre :

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

Charger un fichier dans un répertoire

Vous pouvez charger du contenu dans un fichier nouveau ou existant à l’aide de la méthode suivante :

L’exemple de code suivant montre comment charger un fichier local dans un répertoire à l’aide de la UploadAsync méthode :

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

Vous pouvez utiliser cette méthode pour créer et charger du contenu dans un nouveau fichier, ou vous pouvez définir le overwrite paramètre sur true pour remplacer un fichier existant.

Ajouter des données à un fichier

Vous pouvez charger des données à ajouter à un fichier à l’aide de la méthode suivante :

L’exemple de code suivant montre comment ajouter des données à la fin d’un fichier en procédant comme suit :

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

Télécharger à partir d’un répertoire

L’exemple de code suivant montre comment télécharger un fichier à partir d’un répertoire vers un fichier local en procédant comme suit :

  • Créez une instance DataLakeFileClient pour représenter le fichier que vous souhaitez télécharger.
  • Utilisez la méthode DataLakeFileClient.ReadAsync puis analysez la valeur retournée pour obtenir un objet Stream. Utilisez n’importe quelle API de traitement de fichiers .NET pour enregistrer les octets du flux de données dans un fichier.

Cet exemple utilise un objet BinaryReader et un objet FileStream pour enregistrer des octets dans un fichier.

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

Afficher le contenu du répertoire

Vous pouvez répertorier le contenu du répertoire à l’aide de la méthode suivante et énumérer le résultat :

L’énumération des chemins d’accès dans le résultat peut faire plusieurs requêtes au service lors de l’extraction des valeurs.

L’exemple de code suivant affiche les noms de chaque fichier situé dans un répertoire :

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

}

Supprimer un répertoire

Vous pouvez supprimer un répertoire à l’aide de la méthode suivante :

L’exemple de code suivant montre comment supprimer un répertoire :

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

    await directoryClient.DeleteAsync();
}

Restaurer un répertoire supprimé de manière réversible

Vous pouvez utiliser les bibliothèques de client du Stockage Azure pour restaurer un répertoire supprimé de manière réversible. Utilisez la méthode suivante pour répertorier les chemins d’accès supprimés d’une instance DataLakeFileSystemClient :

Utilisez la méthode suivante pour restaurer un répertoire supprimé de manière réversible :

L’exemple de code suivant montre comment répertorier les chemins d’accès supprimés et restaurer un répertoire supprimé de manière réversible :

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

Si vous renommez le répertoire qui contient les éléments supprimés de manière réversible, ces éléments sont déconnectés du répertoire. Si vous souhaitez restaurer ces éléments, vous devez rétablir le nom d’origine du répertoire ou créer un répertoire distinct qui utilise le nom de répertoire d’origine. Dans le cas contraire, vous recevez une erreur lorsque vous tentez de restaurer ces éléments supprimés de manière réversible.

Obtenir une SAP de délégation d’utilisateur pour un répertoire

Pour utiliser les exemples de code de cette section, ajoutez la directive using suivante :

using Azure.Storage.Sas;

L’exemple de code suivant montre comment générer une SAP de délégation d’utilisateur pour un répertoire lorsqu’un espace de noms hiérarchique est activé pour le compte de stockage :

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

L’exemple suivant teste la SAP de délégation d’utilisateur créée dans l’exemple précédent à partir d’une application cliente simulée. Si la SAP est valide, l’application cliente est en mesure de répertorier les chemins d’accès aux fichiers de ce répertoire. Si la SAP n’est pas valide (par exemple, si elle a expiré), le service de stockage retourne le code d’erreur 403 (Interdit).

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

Pour en savoir plus sur la création d’une SAP de délégation d’utilisateur, consultez Créer une SAP de délégation d’utilisateur avec .NET.

Créer une SAS de service pour un répertoire

Dans un compte de stockage doté d’un espace de noms hiérarchique activé, vous pouvez créer une SAS de service pour un répertoire. Pour créer la SAS de service, assurez-vous d’avoir installé la version 12.5.0 ou ultérieure du package Azure.Storage.Files.DataLake.

L’exemple suivant montre comment créer une SAS de service destinée à un répertoire :

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

Pour en savoir plus sur la création d’une SAP de service, consultez Créer une SAP de service avec .NET.

Voir aussi