Zarządzanie katalogami i plikami w usłudze Azure Data Lake Storage Gen2 przy użyciu platformy .NET

W tym artykule pokazano, jak używać platformy .NET do tworzenia katalogów i plików oraz plików na kontach magazynu, które mają hierarchiczną przestrzeń nazw.

Aby dowiedzieć się, jak pobierać, ustawiać i aktualizować listy kontroli dostępu (ACL) katalogów i plików, zobacz Zarządzanie listami ACL w usłudze Azure Data Lake Storage Gen2 przy użyciu platformy .NET.

Package (NuGet)Samples | API reference Gen1 to Gen2 mapping Give Feedback (Dokumentacja interfejsu API pakietów (NuGet) | Dokumentacja | interfejsu API gen1 do mapowania | gen2

Wymagania wstępne

konfigurowanie projektu

Aby rozpocząć, zainstaluj pakiet NuGet Azure.Storage.Files.DataLake .

Aby uzyskać więcej informacji na temat sposobu instalowania pakietów NuGet, zobacz Instalowanie pakietów i zarządzanie nimi w programie Visual Studio przy użyciu Menedżer pakietów NuGet.

Następnie dodaj te instrukcje using na początku pliku kodu.

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

Uwaga

Dostęp do wielu protokołów w usłudze Data Lake Storage umożliwia aplikacjom korzystanie zarówno z interfejsów API obiektów blob, jak i interfejsów API usługi Data Lake Storage Gen2 do pracy z danymi na kontach magazynu z włączoną hierarchiczną przestrzenią nazw (HNS). Podczas pracy z funkcjami unikatowymi dla usługi Data Lake Storage Gen2, takimi jak operacje katalogów i listy ACL, użyj interfejsów API usługi Data Lake Storage Gen2, jak pokazano w tym artykule.

Podczas wybierania interfejsów API, które mają być używane w danym scenariuszu, należy wziąć pod uwagę obciążenie i potrzeby aplikacji wraz ze znanymi problemami i wpływem sieci HNS na obciążenia i aplikacje.

Autoryzowanie dostępu i nawiązywanie połączenia z zasobami danych

Aby pracować z przykładami kodu w tym artykule, należy utworzyć autoryzowane wystąpienie Elementu DataLakeServiceClient reprezentujące konto magazynu. Obiekt można autoryzować DataLakeServiceClient przy użyciu identyfikatora Entra firmy Microsoft, klucza dostępu do konta lub sygnatury dostępu współdzielonego (SAS).

Bibliotekę klienta tożsamości platformy Azure dla platformy .NET można użyć do uwierzytelniania aplikacji za pomocą identyfikatora Entra firmy Microsoft.

Utwórz wystąpienie Elementu DataLakeServiceClient i przekaż nowe wystąpienie klasy 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;
}

Aby dowiedzieć się więcej na temat autoryzowania DefaultAzureCredential dostępu do danych, zobacz Jak uwierzytelniać aplikacje platformy .NET za pomocą usług platformy Azure.

Tworzenie kontenera

Kontener działa jako system plików. Kontener można utworzyć przy użyciu następującej metody:

Poniższy przykład kodu tworzy kontener i zwraca obiekt DataLakeFileSystemClient do późniejszego użycia:

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

Tworzenie katalogu

Odwołanie do katalogu można utworzyć w kontenerze przy użyciu następującej metody:

Poniższy przykład kodu dodaje katalog do kontenera, a następnie dodaje podkatalog i zwraca obiekt DataLakeDirectoryClient do późniejszego użycia:

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

    return await directoryClient.CreateSubDirectoryAsync(subdirectoryName);
}

Zmienianie nazwy lub przenoszenie katalogu

Możesz zmienić nazwę lub przenieść katalog przy użyciu następującej metody:

Przekaż ścieżkę żądanego katalogu jako parametr. W poniższym przykładzie kodu pokazano, jak zmienić nazwę podkatalogu:

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

Poniższy przykład kodu pokazuje, jak przenieść podkatalog z jednego katalogu do innego katalogu:

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

Przekazywanie pliku do katalogu

Zawartość można przekazać do nowego lub istniejącego pliku przy użyciu następującej metody:

W poniższym przykładzie kodu pokazano, jak przekazać plik lokalny do katalogu przy użyciu UploadAsync metody :

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

Za pomocą tej metody można utworzyć i przekazać zawartość do nowego pliku lub ustawić parametr na wartość , overwrite aby true zastąpić istniejący plik.

Dołączanie danych do pliku

Dane do dołączenia do pliku można przekazać przy użyciu następującej metody:

Poniższy przykład kodu pokazuje, jak dołączyć dane na końcu pliku, wykonując następujące kroki:

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

Pobieranie z katalogu

Poniższy przykład kodu pokazuje, jak pobrać plik z katalogu do pliku lokalnego, wykonując następujące kroki:

W tym przykładzie użyto elementu BinaryReader i elementu FileStream do zapisywania bajtów w pliku.

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

Wyświetlanie zawartości katalogu

Zawartość katalogu można wyświetlić przy użyciu następującej metody i wyliczyć wynik:

Wyliczanie ścieżek w wyniku może wysyłać wiele żądań do usługi podczas pobierania wartości.

Poniższy przykład kodu wyświetla nazwy każdego pliku znajdującego się w katalogu:

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

}

Usuwanie katalogu

Katalog można usunąć przy użyciu następującej metody:

W poniższym przykładzie kodu pokazano, jak usunąć katalog:

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

    await directoryClient.DeleteAsync();
}

Przywracanie katalogu usuniętego nietrwale

Biblioteki klienta usługi Azure Storage umożliwiają przywrócenie katalogu usuniętego nietrwale. Użyj następującej metody, aby wyświetlić listę usuniętych ścieżek dla wystąpienia klasy DataLakeFileSystemClient :

Użyj następującej metody, aby przywrócić katalog usunięty nietrwale:

W poniższym przykładzie kodu pokazano, jak wyświetlić listę usuniętych ścieżek i przywrócić katalog usunięty nietrwale:

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

Jeśli zmienisz nazwę katalogu zawierającego elementy usunięte nietrwale, te elementy zostaną odłączone od katalogu. Jeśli chcesz przywrócić te elementy, musisz przywrócić nazwę katalogu z powrotem do oryginalnej nazwy lub utworzyć oddzielny katalog, który używa oryginalnej nazwy katalogu. W przeciwnym razie podczas próby przywrócenia tych nietrwałych elementów zostanie wyświetlony błąd.

Tworzenie sygnatury dostępu współdzielonego delegowania użytkownika dla katalogu

Aby pracować z przykładami kodu w tej sekcji, dodaj następującą using dyrektywę:

using Azure.Storage.Sas;

Poniższy przykład kodu pokazuje, jak wygenerować sygnaturę dostępu współdzielonego delegowania użytkownika dla katalogu, gdy hierarchiczna przestrzeń nazw jest włączona dla konta magazynu:

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

Poniższy przykład testuje sygnaturę dostępu współdzielonego delegowania użytkownika utworzoną w poprzednim przykładzie z symulowanej aplikacji klienckiej. Jeśli sygnatura dostępu współdzielonego jest prawidłowa, aplikacja kliencka może wyświetlić listę ścieżek plików dla tego katalogu. Jeśli sygnatura dostępu współdzielonego jest nieprawidłowa (na przykład sygnatura dostępu współdzielonego wygasła), usługa Storage zwraca kod błędu 403 (Zabronione).

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

Aby dowiedzieć się więcej na temat tworzenia sygnatury dostępu współdzielonego delegowania użytkownika, zobacz Tworzenie sygnatury dostępu współdzielonego delegowania użytkownika za pomocą platformy .NET.

Tworzenie sygnatury dostępu współdzielonego usługi dla katalogu

Na koncie magazynu z włączoną hierarchiczną przestrzenią nazw można utworzyć sygnaturę dostępu współdzielonego usługi dla katalogu. Aby utworzyć sygnaturę dostępu współdzielonego usługi, upewnij się, że zainstalowano wersję 12.5.0 lub nowszą pakietu Azure.Storage.Files.DataLake .

W poniższym przykładzie pokazano, jak utworzyć sygnaturę dostępu współdzielonego usługi dla katalogu:

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

Aby dowiedzieć się więcej na temat tworzenia sygnatury dostępu współdzielonego usługi, zobacz Tworzenie sygnatury dostępu współdzielonego usługi przy użyciu platformy .NET.

Zobacz też