Uso de .NET para administrar directorios y archivos en Azure Data Lake Storage Gen2
En este artículo se explica cómo usar .NET para crear y administrar directorios y archivos en cuentas de almacenamiento que tengan habilitado un espacio de nombres jerárquico.
Para obtener información sobre cómo obtener, establecer y actualizar las listas de control de acceso (ACL) de directorios y archivos, consulte Uso de .NET para administrar listas de control de acceso en Azure Data Lake Storage Gen2.
Paquete (NuGet) | Ejemplos | Referencia de API | Asignación de Gen1 a Gen2 | Envíenos sus comentarios
Requisitos previos
Suscripción a Azure. Consulte Obtención de una versión de evaluación gratuita.
Una cuenta de almacenamiento que tenga habilitado un espacio de nombres jerárquico. Siga estas instrucciones para crear uno.
Configurar su proyecto
Para empezar, instale el paquete NuGet Azure.Storage.Files.DataLake.
Para más información sobre cómo instalar paquetes NuGet, consulte Instalación y administración de paquetes en Visual Studio con el Administrador de paquetes NuGet.
A continuación, agregue estas instrucciones USING al inicio del archivo de código.
using Azure;
using Azure.Storage.Files.DataLake;
using Azure.Storage.Files.DataLake.Models;
using Azure.Storage;
using System.IO;
Nota:
El acceso a varios protocolos en Data Lake Storage permite a las aplicaciones usar las API de blobs y las API de Data Lake Storage Gen2 para trabajar con datos en cuentas de almacenamiento con el espacio de nombres jerárquico (HNS) habilitado. Al trabajar con capacidades exclusivas de Data Lake Storage Gen2, como las operaciones de directorio y las ACL, use las API de Data Lake Storage Gen2, como se muestra en este artículo.
Al elegir qué API usar en un escenario determinado, tenga en cuenta la carga de trabajo y las necesidades de la aplicación, junto con los problemas conocidos y el impacto de HNS en cargas de trabajo y aplicaciones.
Autorización del acceso y conexión a recursos de datos
Para trabajar con los ejemplos de código de este artículo, debe crear una instancia DataLakeServiceClient autorizada que represente la cuenta de almacenamiento. Puede autorizar un objeto DataLakeServiceClient
mediante Microsoft Entra ID, una clave de acceso de cuenta o una firma de acceso compartido (SAS).
Puede usar la biblioteca cliente de identidad de Azure para .NET para autenticar la aplicación con Microsoft Entra ID.
Cree una instancia de DataLakeServiceClient y pase una nueva instancia de la clase 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 obtener más información sobre el uso de DefaultAzureCredential
para autorizar el acceso a los datos, consulte Cómo autenticar aplicaciones .NET con servicios de Azure.
Crear un contenedor
Un contenedor actúa como sistema de archivos para sus archivos. Puede crear un contenedor mediante el método siguiente:
En el siguiente ejemplo se crea un contenedor y se devuelve un objeto DataLakeFileSystemClient para su uso posterior:
public async Task<DataLakeFileSystemClient> CreateFileSystem(
DataLakeServiceClient serviceClient,
string fileSystemName)
{
return await serviceClient.CreateFileSystemAsync(fileSystemName);
}
Creación de un directorio
Puede crear una referencia de directorio en el contenedor mediante el método siguiente:
En el ejemplo de código siguiente se agrega un directorio a un contenedor y, a continuación, se agrega un subdirectorio y se devuelve un objeto DataLakeDirectoryClient para su uso posterior:
public async Task<DataLakeDirectoryClient> CreateDirectory(
DataLakeFileSystemClient fileSystemClient,
string directoryName,
string subdirectoryName)
{
DataLakeDirectoryClient directoryClient =
await fileSystemClient.CreateDirectoryAsync(directoryName);
return await directoryClient.CreateSubDirectoryAsync(subdirectoryName);
}
Cambio de nombre o traslado de un directorio
Puede cambiar el nombre o mover un directorio mediante el método siguiente:
Pase la ruta de acceso del directorio que busca como un parámetro. En el código de ejemplo siguiente, se muestra cómo cambiar el nombre de un subdirectorio:
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));
}
En el ejemplo de código siguiente se muestra cómo mover un subdirectorio de un directorio a otro:
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));
}
Carga de un archivo en un directorio
Puede cargar contenido en un archivo nuevo o en uno ya existente, mediante el método siguiente:
En el ejemplo de código siguiente se muestra cómo cargar un archivo local en un directorio mediante el método UploadAsync
:
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);
}
Puede usar este método para crear y cargar contenido en un archivo nuevo, o bien puede establecer el parámetro overwrite
en true
para sobrescribir un archivo existente.
Anexión de datos a un archivo
Puede cargar los datos que se van a anexar a un archivo mediante el método siguiente:
En el ejemplo de código siguiente se muestra cómo anexar datos al final de un archivo mediante estos pasos:
- Cree un objeto DataLakeFileClient para representar el recurso de archivo con el que está trabajando.
- Cargue datos en el archivo mediante el método DataLakeFileClient.AppendAsync.
- Complete la carga llamando al método DataLakeFileClient.FlushAsync para escribir los datos cargados anteriormente en el archivo.
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);
}
Descarga de un directorio
En el ejemplo de código siguiente se muestra cómo descargar un archivo de un directorio a un archivo local mediante estos pasos:
- Cree una instancia de DataLakeFileClient que represente al archivo que quiere descargar.
- Use el método DataLakeFileClient.ReadAsync y analice el valor devuelto para obtener un objeto Stream. Use cualquier archivo .NET que procese API para guardar bytes de la transmisión en un archivo.
En este ejemplo se usa BinaryReader y FileStream para guardar bytes en un archivo.
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();
}
Lista del contenido del directorio
Puede crear una lista del contenido del directorio mediante el método siguiente y enumerar el resultado:
La enumeración de las rutas de acceso en el resultado puede realizar varias solicitudes al servicio mientas captura los valores.
En este código de ejemplo, se imprimen los nombres de cada uno de los archivos que se ubican en un directorio:
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;
}
}
Eliminación de un directorio
Puede eliminar un directorio mediante el método siguiente:
En el código de ejemplo siguiente, se muestra cómo eliminar un directorio:
public async Task DeleteDirectory(
DataLakeFileSystemClient fileSystemClient,
string directoryName)
{
DataLakeDirectoryClient directoryClient =
fileSystemClient.GetDirectoryClient(directoryName);
await directoryClient.DeleteAsync();
}
Restauración de un directorio eliminado temporalmente
Puede usar las bibliotecas cliente de Azure Storage para restaurar un directorio eliminado temporalmente. Use el método siguiente para enumerar las rutas de acceso eliminadas de una instancia de DataLakeFileSystemClient:
Use el método siguiente para restaurar un directorio eliminado temporalmente:
En el ejemplo de código siguiente se muestra cómo enumerar las rutas de acceso eliminadas y restaurar un directorio eliminado temporalmente:
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 cambia el nombre del directorio que contiene los elementos eliminados temporalmente, esos elementos se desconectan del directorio. Si desea restaurar esos elementos, tiene que revertir el nombre del directorio al nombre original o crear un directorio independiente que use el nombre del directorio original. De lo contrario, recibe un error al intentar restaurar esos elementos eliminados temporalmente.
Crear una SAS de delegación de usuarios para un directorio
Para trabajar con los ejemplos de código de esta sección, agregue la siguiente directiva de using
:
using Azure.Storage.Sas;
En el ejemplo de código siguiente se muestra cómo generar una SAS de delegación de usuarios para un directorio cuando hay un espacio de nombres jerárquico habilitado para la cuenta de almacenamiento:
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;
}
}
En el ejemplo siguiente se prueba la SAS de delegación de usuarios creada en el ejemplo anterior desde una aplicación cliente simulada. Si la SAS es válida, la aplicación cliente puede mostrar las rutas de acceso de archivo de este directorio. Si la SAS no es válida (por ejemplo, si ha expirado la SAS), el servicio Storage devuelve el código de error 403 (prohibido).
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 más información sobre cómo crear una SAS de delegación de usuario, consulte Creación de una SAS de delegación de usuario con .NET.
Creación de una SAS de servicio para un directorio
En una cuenta de almacenamiento con un espacio de nombres jerárquico habilitado, puede crear una SAS de servicio para un directorio. Para crear la SAS de servicio, asegúrese de que ha instalado la versión 12.5.0 o posterior del paquete Azure.Storage.Files.DataLake.
En el ejemplo siguiente se muestra cómo crear una SAS de servicio para un directorio:
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 más información sobre cómo crear una SAS de servicio, consulte Creación de una SAS de servicio con .NET.