Usare .NET per gestire directory e file in Azure Data Lake Archiviazione Gen2

Questo articolo illustra come usare .NET per creare e gestire directory e file negli account di archiviazione con uno spazio dei nomi gerarchico.

Per informazioni su come ottenere, impostare e aggiornare gli elenchi di controllo di accesso (ACL) di directory e file, vedere Usare .NET per gestire gli elenchi di controllo di accesso in Azure Data Lake Archiviazione Gen2.

Riferimento all'API Package (NuGet) | Samples | Gen1 to Gen2 mapping | Give Feedback |

Prerequisiti

Impostare il progetto

Per iniziare, installare Azure.Archiviazione. Pacchetto NuGet Files.DataLake.

Per altre informazioni su come installare pacchetti NuGet, vedere Installare e gestire i pacchetti in Visual Studio usando il Gestione pacchetti NuGet.

Aggiungere quindi queste istruzioni using all'inizio del file di codice.

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

Nota

L'accesso multi-protocollo in Data Lake Archiviazione consente alle applicazioni di usare sia le API BLOB che le API Data Lake Archiviazione Gen2 per lavorare con i dati negli account di archiviazione con lo spazio dei nomi gerarchico (HNS) abilitato. Quando si usano funzionalità specifiche di Data Lake Archiviazione Gen2, ad esempio le operazioni di directory e gli ACL, usare le API Data Lake Archiviazione Gen2, come illustrato in questo articolo.

Quando si scelgono le API da usare in uno scenario specifico, prendere in considerazione il carico di lavoro e le esigenze dell'applicazione, insieme ai problemi noti e all'impatto di HNS su carichi di lavoro e applicazioni.

Autorizzare l'accesso e connettersi alle risorse dati

Per usare gli esempi di codice in questo articolo, è necessario creare un'istanza di DataLakeServiceClient autorizzata che rappresenta l'account di archiviazione. È possibile autorizzare un DataLakeServiceClient oggetto usando l'ID Microsoft Entra, una chiave di accesso all'account o una firma di accesso condiviso.

È possibile usare la libreria client di identità di Azure per .NET per autenticare l'applicazione con Microsoft Entra ID.

Creare un'istanza di DataLakeServiceClient e passare una nuova istanza della 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;
}

Per altre informazioni sull'uso DefaultAzureCredential di per autorizzare l'accesso ai dati, vedere Come autenticare le applicazioni .NET con i servizi di Azure.

Creazione di un contenitore

Un contenitore funge da file system per i file. È possibile creare un contenitore usando il metodo seguente:

Nell'esempio di codice seguente viene creato un contenitore e viene restituito un oggetto DataLakeFileSystemClient per un uso successivo:

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

Creare una directory

È possibile creare un riferimento alla directory nel contenitore usando il metodo seguente:

L'esempio di codice seguente aggiunge una directory a un contenitore, quindi aggiunge una sottodirectory e restituisce un oggetto DataLakeDirectoryClient per un uso successivo:

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

    return await directoryClient.CreateSubDirectoryAsync(subdirectoryName);
}

Rinominare o spostare una directory

È possibile rinominare o spostare una directory usando il metodo seguente:

Passare il percorso della directory desiderata come parametro. L'esempio di codice seguente illustra come rinominare una sottodirectory:

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

Nell'esempio di codice seguente viene illustrato come spostare una sottodirectory da una directory a una directory diversa:

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

Caricare un file in una directory

È possibile caricare contenuto in un file nuovo o esistente usando il metodo seguente:

L'esempio di codice seguente illustra come caricare un file locale in una directory usando il UploadAsync metodo :

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

È possibile usare questo metodo per creare e caricare contenuto in un nuovo file oppure impostare il overwrite parametro su true per sovrascrivere un file esistente.

Accodare dati a un file

È possibile caricare i dati da aggiungere a un file usando il metodo seguente:

Nell'esempio di codice seguente viene illustrato come aggiungere dati alla fine di un file attenendosi alla procedura seguente:

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

Scaricare da una directory

Nell'esempio di codice seguente viene illustrato come scaricare un file da una directory in un file locale attenendosi alla procedura seguente:

Questo esempio usa BinaryReader e FileStream per salvare i byte in un file.

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

Elencare il contenuto della directory

È possibile elencare il contenuto della directory usando il metodo seguente ed enumerando il risultato:

L'enumerazione dei percorsi nel risultato può effettuare più richieste al servizio durante il recupero dei valori.

L'esempio di codice seguente stampa i nomi di ogni file che si trova in una directory:

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

}

Eliminare una directory

È possibile eliminare una directory usando il metodo seguente:

Nell'esempio di codice seguente viene illustrato come eliminare una directory:

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

    await directoryClient.DeleteAsync();
}

Ripristinare una directory eliminata temporanea

È possibile usare le librerie client Archiviazione di Azure per ripristinare una directory eliminata temporanea. Usare il metodo seguente per elencare i percorsi eliminati per un'istanza di DataLakeFileSystemClient :

Usare il metodo seguente per ripristinare una directory eliminata temporanea:

Nell'esempio di codice seguente viene illustrato come elencare i percorsi eliminati e ripristinare una directory eliminata temporanea:

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 si rinomina la directory che contiene gli elementi eliminati temporaneamente, tali elementi vengono disconnessi dalla directory. Se si desidera ripristinare tali elementi, è necessario ripristinare il nome della directory al nome originale o creare una directory separata che utilizza il nome della directory originale. In caso contrario, viene visualizzato un errore quando si tenta di ripristinare gli elementi eliminati temporaneo.

Creare una firma di accesso condiviso di delega utente per una directory

Per usare gli esempi di codice in questa sezione, aggiungere la direttiva seguente using :

using Azure.Storage.Sas;

L'esempio di codice seguente illustra come generare una firma di accesso condiviso di delega utente per una directory quando uno spazio dei nomi gerarchico è abilitato per l'account di archiviazione:

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

Nell'esempio seguente viene verificata la firma di accesso condiviso di delega utente creata nell'esempio precedente da un'applicazione client simulata. Se la firma di accesso condiviso è valida, l'applicazione client è in grado di elencare i percorsi di file per questa directory. Se la firma di accesso condiviso non è valida(ad esempio, la firma di accesso condiviso è scaduta), il servizio Archiviazione restituisce il codice di errore 403 (Accesso negato).

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

Per altre informazioni sulla creazione di una firma di accesso condiviso di delega utente, vedere Creare una firma di accesso condiviso per la delega utente con .NET.

Creare una firma di accesso condiviso del servizio per una directory

In un account di archiviazione con uno spazio dei nomi gerarchico abilitato è possibile creare una firma di accesso condiviso del servizio per una directory. Per creare la firma di accesso condiviso del servizio, assicurarsi di aver installato la versione 12.5.0 o successiva di Azure.Archiviazione. Pacchetto Files.DataLake.

L'esempio seguente illustra come creare una firma di accesso condiviso del servizio per una directory:

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

Per altre informazioni sulla creazione di una firma di accesso condiviso del servizio, vedere Creare una firma di accesso condiviso del servizio con .NET.

Vedi anche