Partilhar via


Usar o .NET para gerenciar diretórios e arquivos no Armazenamento do Azure Data Lake

Este artigo mostra como usar o .NET para criar e gerenciar diretórios e arquivos em contas de armazenamento que têm um namespace hierárquico.

Para saber como obter, definir e atualizar as listas de controle de acesso (ACL) de diretórios e arquivos, consulte Usar o .NET para gerenciar ACLs no Armazenamento do Azure Data Lake.

Pacote (NuGet) | Amostras | API referência | Gen1 para Gen2 mapeamento | Dar feedback

Pré-requisitos

Configure o seu projeto

Para começar, instale o pacote NuGet Azure.Storage.Files.DataLake .

Para obter mais informações sobre como instalar pacotes NuGet, consulte Instalar e gerenciar pacotes no Visual Studio usando o Gerenciador de Pacotes NuGet.

Em seguida, adicione essas instruções using à parte superior do arquivo de código.

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

Nota

O acesso multiprotocolo no Data Lake Storage permite que os aplicativos usem APIs de Blob e APIs do Data Lake Storage Gen2 para trabalhar com dados em contas de armazenamento com namespace hierárquico (HNS) habilitado. Ao trabalhar com recursos exclusivos do Data Lake Storage Gen2, como operações de diretório e ACLs, use as APIs do Data Lake Storage Gen2, conforme mostrado neste artigo.

Ao escolher quais APIs usar em um determinado cenário, considere a carga de trabalho e as necessidades do seu aplicativo, juntamente com os problemas conhecidos e o impacto do HNS em cargas de trabalho e aplicativos.

Autorizar o acesso e conectar-se a recursos de dados

Para trabalhar com os exemplos de código neste artigo, você precisa criar uma instância DataLakeServiceClient autorizada que represente a conta de armazenamento. Você pode autorizar um objeto usando o DataLakeServiceClient Microsoft Entra ID, uma chave de acesso de conta ou uma assinatura de acesso compartilhado (SAS).

Você pode usar a biblioteca de cliente de identidade do Azure para .NET para autenticar seu aplicativo com a ID do Microsoft Entra.

Crie uma instância DataLakeServiceClient e passe uma nova instância da 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;
}

Para saber mais sobre como usar DefaultAzureCredential para autorizar o acesso a dados, consulte Como autenticar aplicativos .NET com serviços do Azure.

Criar um contentor

Um contêiner atua como um sistema de arquivos para seus arquivos. Você pode criar um contêiner usando o seguinte método:

O exemplo de código a seguir cria um contêiner e retorna um objeto DataLakeFileSystemClient para uso posterior:

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

Criar um diretório

Você pode criar uma referência de diretório no contêiner usando o seguinte método:

O exemplo de código a seguir adiciona um diretório a um contêiner, adiciona um subdiretório e retorna um objeto DataLakeDirectoryClient para uso posterior:

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

    return await directoryClient.CreateSubDirectoryAsync(subdirectoryName);
}

Renomear ou mover um diretório

Você pode renomear ou mover um diretório usando o seguinte método:

Passe o caminho do diretório desejado como um parâmetro. O exemplo de código a seguir mostra como renomear um subdiretório:

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

O exemplo de código a seguir mostra como mover um subdiretório de um diretório para um diretório diferente:

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

Carregar um ficheiro para um diretório

Você pode carregar conteúdo para um arquivo novo ou existente usando o seguinte método:

O exemplo de código a seguir mostra como carregar um arquivo local para um diretório usando o UploadAsync método:

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

Acrescentar dados a um ficheiro

Você pode carregar dados a serem anexados a um arquivo usando o seguinte método:

O exemplo de código a seguir mostra como acrescentar dados ao final de um arquivo usando estas etapas:

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

Download de um diretório

O exemplo de código a seguir mostra como baixar um arquivo de um diretório para um arquivo local usando estas etapas:

Este exemplo usa um BinaryReader e um FileStream para salvar bytes em um arquivo.

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

Listar conteúdo do diretório

Você pode listar o conteúdo do diretório usando o seguinte método e enumerando o resultado:

Enumerar os caminhos no resultado pode fazer várias solicitações para o serviço ao buscar os valores.

O exemplo de código a seguir imprime os nomes de cada arquivo que está localizado em um diretório:

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

}

Eliminar um diretório

Você pode excluir um diretório usando o seguinte método:

O exemplo de código a seguir mostra como excluir um diretório:

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

    await directoryClient.DeleteAsync();
}

Restaurar um diretório de exclusão suave

Você pode usar as bibliotecas de cliente do Armazenamento do Azure para restaurar um diretório excluído por software. Use o seguinte método para listar caminhos excluídos para uma instância DataLakeFileSystemClient :

Use o seguinte método para restaurar um diretório excluído por software:

O exemplo de código a seguir mostra como listar caminhos excluídos e restaurar um diretório soft-delete:

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

Se você renomear o diretório que contém os itens excluídos por software, esses itens serão desconectados do diretório. Se você quiser restaurar esses itens, você tem que reverter o nome do diretório de volta para seu nome original ou criar um diretório separado que usa o nome do diretório original. Caso contrário, você receberá um erro ao tentar restaurar esses itens excluídos por software.

Criar uma SAS de delegação de usuário para um diretório

Para trabalhar com os exemplos de código nesta seção, adicione a seguinte using diretiva:

using Azure.Storage.Sas;

O exemplo de código a seguir mostra como gerar uma SAS de delegação de usuário para um diretório quando um namespace hierárquico está habilitado para a conta de armazenamento:

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

O exemplo a seguir testa a SAS de delegação de usuário criada no exemplo anterior a partir de um aplicativo cliente simulado. Se a SAS for válida, o aplicativo cliente poderá listar caminhos de arquivo para esse diretório. Se a SAS for inválida (por exemplo, a SAS expirou), o serviço de armazenamento retornará o código de erro 403 (Proibido).

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

Para saber mais sobre como criar uma SAS de delegação de usuário, consulte Criar uma SAS de delegação de usuário com .NET.

Criar uma SAS de serviço para um diretório

Em uma conta de armazenamento com um namespace hierárquico habilitado, você pode criar uma SAS de serviço para um diretório. Para criar o serviço SAS, certifique-se de ter instalado a versão 12.5.0 ou posterior do pacote Azure.Storage.Files.DataLake .

O exemplo a seguir mostra como criar uma SAS de serviço para um diretório:

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

Para saber mais sobre como criar uma SAS de serviço, consulte Criar uma SAS de serviço com .NET.

Consulte também