Разработка для службы файлов Azure с помощью .NET

Ознакомьтесь с основами разработки приложений .NET, которые используют Файлы Azure для хранения данных. В этой статье показано, как создать простое консольное приложение для следующих действий с .NET и Файлами Azure:

  • Получение содержимого файла.
  • Установка максимального размера (квоты) для общей папки.
  • Создание подписанного URL-адреса (SAS) для файла.
  • Скопируйте файл в другой файл в той же учетной записи хранения
  • Скопируйте файл в BLOB-объект в той же учетной записи хранения
  • Создание моментального снимка общей папки.
  • Восстановление файла из моментального снимка общей папки.
  • Использование метрик службы хранилища Azure для устранения неполадок.

Подробные сведения см. в статье о Файлах Azure.

Совет

См. примеры кода в репозитории службы хранилища Azure

Полные и простые в применении примеры кода для службы хранилища Azure можно скачать и запустить отсюда.

Применяется к

Тип общей папки SMB NFS
Стандартные общие папки (GPv2), LRS/ZRS Да Нет
Стандартные общие папки (GPv2), GRS/GZRS Да Нет
Общие папки уровня "Премиум" (FileStorage), LRS/ZRS Да Нет

Основные сведения об API-интерфейсах .NET

Служба файлов Azure предлагает два широких подхода к использованию клиентских приложений: SMB (блок сообщений сервера) и REST. В .NET интерфейсы API System.IO и Azure.Storage.Files.Shares предоставляют средства для использования этих подходов.

API Назначение Примечания
System.IO Требования вашего приложения:
  • чтение и запись файлов по протоколу SMB;
  • выполнение на устройстве, которое получает доступ к учетной записи службы файлов Azure через порт 445;
  • не требуется управлять параметрами администрирования общей папки.
Файловый ввод-вывод, реализованный с помощью Файлов Azure по протоколу SMB, ничем не отличается от операций ввода-вывода в сетевой общей папке или на локальном устройстве хранения. Общие сведения о ряде функций .NET, включая ввод-вывод файлов, см. в руководстве по консольному приложению.
Azure.Storage.Files.Shares Требования вашего приложения:
  • отсутствует доступ к Файлам Azure по протоколу SMB через порт 445 из-за ограничений брандмауэра или поставщика услуг Интернета;
  • требуются административные функции, например возможность задать квоту для общей папки или создать подписанный URL-адрес.
В этой статье приводится пример использования Azure.Storage.Files.Shares для файлового ввода-вывода с помощью REST (вместо SMB) и управления общей папкой.

Создание консольного приложения и получение сборки

Клиентскую библиотеку Файлов Azure можно использовать в любом типе приложения .NET. К таким приложениям относятся веб-приложения, облачные, классические и мобильные приложения Azure. Для упрощения процесса в этом руководстве показано, как создать консольное приложение.

В Visual Studio создайте новое консольное приложение Windows. Ниже показано, как создать консольное приложение в Visual Studio 2019. Эти же действия можно выполнить и в других версиях Visual Studio.

  1. Запустите Visual Studio и щелкните Создать проект
  2. В окне Создание проекта выберите Консольное приложение (.NET Framework) для C# и нажмите кнопку Далее.
  3. В окне Настроить новый проект введите имя приложения и выберите Создать.

Добавьте все примеры кода из этой статьи в класс Program в файле Program.cs.

Установка необходимых пакетов с помощью NuGet

Добавьте в проект ссылки на эти пакеты:

Вы можете использовать NuGet для получения пакетов. Выполните следующие действия.

  1. В обозревателе решений щелкните правой кнопкой мыши ваш проект и выберите Управление пакетами NuGet.

  2. В разделе Диспетчер пакетов NuGet выберите Обзор. Найдите и выберите Azure.Core, а затем нажмите кнопку Установить.

    Будет установлен пакет и его зависимости.

  3. Найдите и установите такие пакеты:

    • Azure.Storage.Blobs
    • Azure.Storage.Files.Shares
    • System.Configuration.ConfigurationManager

Сохранение учетных данных учетной записи хранения в файле App.config

Теперь сохраните данные учетной записи хранения в файле App.config вашего проекта. В обозревателе решений дважды щелкните App.config и измените файл, чтобы он был похож на пример ниже.

Вместо myaccount укажите имя учетной записи хранения, а вместо mykey — ее ключ.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="StorageConnectionString" 
      value="DefaultEndpointsProtocol=https;AccountName=myaccount;AccountKey=mykey;EndpointSuffix=core.windows.net" />
    <add key="StorageAccountName" value="myaccount" />
    <add key="StorageAccountKey" value="mykey" />
  </appSettings>
</configuration>

Примечание

Эмулятор хранилища Azurite в настоящий момент не поддерживает Файлы Azure. Для работы с Файлами Azure необходимо, чтобы строка подключения указывала на учетную запись хранения Azure в облаке.

Добавление директив using

В обозревателе решений откройте файл Program.cs и добавьте следующие директивы using в начало файла.

using System;
using System.Configuration;
using System.IO;
using System.Threading.Tasks;
using Azure;
using Azure.Storage;
using Azure.Storage.Blobs;
using Azure.Storage.Files.Shares;
using Azure.Storage.Files.Shares.Models;
using Azure.Storage.Sas;

Доступ к общей папке программным путем

Добавьте следующий код в файл Program.cs для программного доступа к общей папке.

Следующий метод создает общую папку, если она еще не существует. Метод сначала создает объект ShareClient из строки подключения. Затем в примере выполняется попытка скачать созданный ранее файл. Вызовите этот метод из Main().

//-------------------------------------------------
// Create a file share
//-------------------------------------------------
public async Task CreateShareAsync(string shareName)
{
    // Get the connection string from app settings
    string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

    // Instantiate a ShareClient which will be used to create and manipulate the file share
    ShareClient share = new ShareClient(connectionString, shareName);

    // Create the share if it doesn't already exist
    await share.CreateIfNotExistsAsync();

    // Ensure that the share exists
    if (await share.ExistsAsync())
    {
        Console.WriteLine($"Share created: {share.Name}");

        // Get a reference to the sample directory
        ShareDirectoryClient directory = share.GetDirectoryClient("CustomLogs");

        // Create the directory if it doesn't already exist
        await directory.CreateIfNotExistsAsync();

        // Ensure that the directory exists
        if (await directory.ExistsAsync())
        {
            // Get a reference to a file object
            ShareFileClient file = directory.GetFileClient("Log1.txt");

            // Ensure that the file exists
            if (await file.ExistsAsync())
            {
                Console.WriteLine($"File exists: {file.Name}");

                // Download the file
                ShareFileDownloadInfo download = await file.DownloadAsync();

                // Save the data to a local file, overwrite if the file already exists
                using (FileStream stream = File.OpenWrite(@"downloadedLog1.txt"))
                {
                    await download.Content.CopyToAsync(stream);
                    await stream.FlushAsync();
                    stream.Close();

                    // Display where the file was saved
                    Console.WriteLine($"File downloaded: {stream.Name}");
                }
            }
        }
    }
    else
    {
        Console.WriteLine($"CreateShareAsync failed");
    }
}

Установка максимального размера для файлового ресурса

Клиентская библиотека Файлов Azure версии 5.x и выше позволяет задавать квоту (максимальный размер) для общей папки. Можно также проверить, какой объем данных хранится в настоящее время в общей папке.

Квота ограничивает общий размер хранящихся в общей папке файлов. Если общий размер файлов в общей папке превышает квоту, клиенты не могут увеличить размер существующих файлов. Клиенты также не могут создавать новые файлы, если эти файлы не пустые.

В приведенном ниже примере показано, как проверить текущее использование данных в файловом ресурсе, а также задать для него квоту.

//-------------------------------------------------
// Set the maximum size of a share
//-------------------------------------------------
public async Task SetMaxShareSizeAsync(string shareName, int increaseSizeInGiB)
{
    const long ONE_GIBIBYTE = 10737420000; // Number of bytes in 1 gibibyte

    // Get the connection string from app settings
    string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

    // Instantiate a ShareClient which will be used to access the file share
    ShareClient share = new ShareClient(connectionString, shareName);

    // Create the share if it doesn't already exist
    await share.CreateIfNotExistsAsync();

    // Ensure that the share exists
    if (await share.ExistsAsync())
    {
        // Get and display current share quota
        ShareProperties properties = await share.GetPropertiesAsync();
        Console.WriteLine($"Current share quota: {properties.QuotaInGB} GiB");

        // Get and display current usage stats for the share
        ShareStatistics stats = await share.GetStatisticsAsync();
        Console.WriteLine($"Current share usage: {stats.ShareUsageInBytes} bytes");

        // Convert current usage from bytes into GiB
        int currentGiB = (int)(stats.ShareUsageInBytes / ONE_GIBIBYTE);

        // This line sets the quota to be the current 
        // usage of the share plus the increase amount
        await share.SetQuotaAsync(currentGiB + increaseSizeInGiB);

        // Get the new quota and display it
        properties = await share.GetPropertiesAsync();
        Console.WriteLine($"New share quota: {properties.QuotaInGB} GiB");
    }
}

Создание подписи общего доступа для файла или файлового ресурса

Начиная с версии 5.x клиентской библиотеки Файлов Azure, можно создать подписанный URL-адрес (SAS) для общей папки или отдельного файла.

В следующем примере метод возвращает SAS для файла в указанной общей папке.

//-------------------------------------------------
// Create a SAS URI for a file
//-------------------------------------------------
public Uri GetFileSasUri(string shareName, string filePath, DateTime expiration, ShareFileSasPermissions permissions)
{
    // Get the account details from app settings
    string accountName = ConfigurationManager.AppSettings["StorageAccountName"];
    string accountKey = ConfigurationManager.AppSettings["StorageAccountKey"];

    ShareSasBuilder fileSAS = new ShareSasBuilder()
    {
        ShareName = shareName,
        FilePath = filePath,

        // Specify an Azure file resource
        Resource = "f",

        // Expires in 24 hours
        ExpiresOn = expiration
    };

    // Set the permissions for the SAS
    fileSAS.SetPermissions(permissions);

    // Create a SharedKeyCredential that we can use to sign the SAS token
    StorageSharedKeyCredential credential = new StorageSharedKeyCredential(accountName, accountKey);

    // Build a SAS URI
    UriBuilder fileSasUri = new UriBuilder($"https://{accountName}.file.core.windows.net/{fileSAS.ShareName}/{fileSAS.FilePath}");
    fileSasUri.Query = fileSAS.ToSasQueryParameters(credential).ToString();

    // Return the URI
    return fileSasUri.Uri;
}

Дополнительные сведения о создании и использовании SAS см. в статье Принцип работы подписанного URL-адреса.

Копирование файлов

Начиная с версии 5.x клиентской библиотеки Файлов Azure, можно скопировать файл в другой файл, файл в BLOB-объект или BLOB-объект в файл.

AzCopy можно использовать для копирования одного файла в другой, а также копирования BLOB-объекта в файл или наоборот. См. подробнее о начале работы с AzCopy.

Примечание

При копировании большого двоичного объекта в файл или файла в большой двоичный объект необходимо использовать подписанный URL-адрес (SAS) для авторизации доступа к исходному объекту, даже если копирование производится внутри одной и той же учетной записи хранения.

Копирование файла в другой файл

В приведенном ниже примере файл копируется в другой файл в той же общей папке. Для копирования можно использовать проверку подлинности с помощью общего ключа, так как эта операция копирует файлы в одну и ту же учетную запись хранения.

//-------------------------------------------------
// Copy file within a directory
//-------------------------------------------------
public async Task CopyFileAsync(string shareName, string sourceFilePath, string destFilePath)
{
    // Get the connection string from app settings
    string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

    // Get a reference to the file we created previously
    ShareFileClient sourceFile = new ShareFileClient(connectionString, shareName, sourceFilePath);

    // Ensure that the source file exists
    if (await sourceFile.ExistsAsync())
    {
        // Get a reference to the destination file
        ShareFileClient destFile = new ShareFileClient(connectionString, shareName, destFilePath);

        // Start the copy operation
        await destFile.StartCopyAsync(sourceFile.Uri);

        if (await destFile.ExistsAsync())
        {
            Console.WriteLine($"{sourceFile.Uri} copied to {destFile.Uri}");
        }
    }
}

Копирование файла в большой двоичный объект

В приведенном ниже примере файл создается и копируется в большой двоичный объект в пределах одной и той же учетной записи хранения. В примере для исходного файла создается SAS, который служба использует для авторизации доступа к исходному файлу во время операции копирования.

//-------------------------------------------------
// Copy a file from a share to a blob
//-------------------------------------------------
public async Task CopyFileToBlobAsync(string shareName, string sourceFilePath, string containerName, string blobName)
{
    // Get a file SAS from the method created ealier
    Uri fileSasUri = GetFileSasUri(shareName, sourceFilePath, DateTime.UtcNow.AddHours(24), ShareFileSasPermissions.Read);

    // Get a reference to the file we created previously
    ShareFileClient sourceFile = new ShareFileClient(fileSasUri);

    // Ensure that the source file exists
    if (await sourceFile.ExistsAsync())
    {
        // Get the connection string from app settings
        string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

        // Get a reference to the destination container
        BlobContainerClient container = new BlobContainerClient(connectionString, containerName);

        // Create the container if it doesn't already exist
        await container.CreateIfNotExistsAsync();

        BlobClient destBlob = container.GetBlobClient(blobName);

        await destBlob.StartCopyFromUriAsync(sourceFile.Uri);

        if (await destBlob.ExistsAsync())
        {
            Console.WriteLine($"File {sourceFile.Name} copied to blob {destBlob.Name}");
        }
    }
}

Таким же образом можно скопировать BLOB-объект в файл. Если исходным объектом является большой двоичный объект, создайте SAS для авторизации доступа к этому объекту во время операции копирования.

Моментальные снимки общих ресурсов

Начиная с версии 8.5 клиентской библиотеки Файлов Azure, можно создавать моментальные снимки общих папок. Можно также получить список моментальных снимков общих ресурсов, просмотреть и удалить их. Созданные моментальные снимки доступны только для чтения.

Создание моментальных снимков общих ресурсов

В следующем примере создается моментальный снимок общего файлового ресурса.

//-------------------------------------------------
// Create a share snapshot
//-------------------------------------------------
public async Task CreateShareSnapshotAsync(string shareName)
{
    // Get the connection string from app settings
    string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

    // Instatiate a ShareServiceClient
    ShareServiceClient shareServiceClient = new ShareServiceClient(connectionString);

    // Instantiate a ShareClient which will be used to access the file share
    ShareClient share = shareServiceClient.GetShareClient(shareName);

    // Ensure that the share exists
    if (await share.ExistsAsync())
    {
        // Create a snapshot
        ShareSnapshotInfo snapshotInfo = await share.CreateSnapshotAsync();
        Console.WriteLine($"Snapshot created: {snapshotInfo.Snapshot}");
    }
}

Вывод списка моментальных снимков общих ресурсов

В примере ниже перечисляются моментальные снимки общей папки.

//-------------------------------------------------
// List the snapshots on a share
//-------------------------------------------------
public void ListShareSnapshots()
{
    // Get the connection string from app settings
    string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

    // Instatiate a ShareServiceClient
    ShareServiceClient shareServiceClient = new ShareServiceClient(connectionString);

    // Display each share and the snapshots on each share
    foreach (ShareItem item in shareServiceClient.GetShares(ShareTraits.All, ShareStates.Snapshots))
    {
        if (null != item.Snapshot)
        {
            Console.WriteLine($"Share: {item.Name}\tSnapshot: {item.Snapshot}");
        }
    }
}

Вывод списка файлов и каталогов в моментальных снимках общих папок

В примере ниже показано, как просмотреть файлы и каталоги в моментальных снимках общей папки.

//-------------------------------------------------
// List the snapshots on a share
//-------------------------------------------------
public void ListSnapshotContents(string shareName, string snapshotTime)
{
    // Get the connection string from app settings
    string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

    // Instatiate a ShareServiceClient
    ShareServiceClient shareService = new ShareServiceClient(connectionString);

    // Get a ShareClient
    ShareClient share = shareService.GetShareClient(shareName);

    Console.WriteLine($"Share: {share.Name}");

    // Get as ShareClient that points to a snapshot
    ShareClient snapshot = share.WithSnapshot(snapshotTime);

    // Get the root directory in the snapshot share
    ShareDirectoryClient rootDir = snapshot.GetRootDirectoryClient();

    // Recursively list the directory tree
    ListDirTree(rootDir);
}

//-------------------------------------------------
// Recursively list a directory tree
//-------------------------------------------------
public void ListDirTree(ShareDirectoryClient dir)
{
    // List the files and directories in the snapshot
    foreach (ShareFileItem item in dir.GetFilesAndDirectories())
    {
        if (item.IsDirectory)
        {
            Console.WriteLine($"Directory: {item.Name}");
            ShareDirectoryClient subDir = dir.GetSubdirectoryClient(item.Name);
            ListDirTree(subDir);
        }
        else
        {
            Console.WriteLine($"File: {dir.Name}\\{item.Name}");
        }
    }
}

Восстановление общих папок или файлов из моментальных снимков общих папок

Создание моментального снимка общей папки позволяет восстановить отдельные файлы или всю общую папку.

Файл можно восстановить из моментального снимка, сделав запрос на моментальные снимки файлового ресурса. Затем можно получить файл, принадлежащий определенному моментальному снимку общей папки. Используйте эту версию для непосредственного чтения или восстановления файла.

//-------------------------------------------------
// Restore file from snapshot
//-------------------------------------------------
public async Task RestoreFileFromSnapshot(string shareName, string directoryName, string fileName, string snapshotTime)
{
    // Get the connection string from app settings
    string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

    // Instatiate a ShareServiceClient
    ShareServiceClient shareService = new ShareServiceClient(connectionString);

    // Get a ShareClient
    ShareClient share = shareService.GetShareClient(shareName);

    // Get as ShareClient that points to a snapshot
    ShareClient snapshot = share.WithSnapshot(snapshotTime);

    // Get a ShareDirectoryClient, then a ShareFileClient to the snapshot file
    ShareDirectoryClient snapshotDir = snapshot.GetDirectoryClient(directoryName);
    ShareFileClient snapshotFile = snapshotDir.GetFileClient(fileName);

    // Get a ShareDirectoryClient, then a ShareFileClient to the live file
    ShareDirectoryClient liveDir = share.GetDirectoryClient(directoryName);
    ShareFileClient liveFile = liveDir.GetFileClient(fileName);

    // Restore the file from the snapshot
    ShareFileCopyInfo copyInfo = await liveFile.StartCopyAsync(snapshotFile.Uri);

    // Display the status of the operation
    Console.WriteLine($"Restore status: {copyInfo.CopyStatus}");
}

Удаление моментальных снимков общих ресурсов

В следующем примере удаляется моментальный снимок общего файлового ресурса.

//-------------------------------------------------
// Delete a snapshot
//-------------------------------------------------
public async Task DeleteSnapshotAsync(string shareName, string snapshotTime)
{
    // Get the connection string from app settings
    string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

    // Instatiate a ShareServiceClient
    ShareServiceClient shareService = new ShareServiceClient(connectionString);

    // Get a ShareClient
    ShareClient share = shareService.GetShareClient(shareName);

    // Get a ShareClient that points to a snapshot
    ShareClient snapshotShare = share.WithSnapshot(snapshotTime);

    try
    {
        // Delete the snapshot
        await snapshotShare.DeleteIfExistsAsync();
    }
    catch (RequestFailedException ex)
    {
        Console.WriteLine($"Exception: {ex.Message}");
        Console.WriteLine($"Error code: {ex.Status}\t{ex.ErrorCode}");
    }
}

Устранение неполадок в работе службы "Файлы Azure" с помощью метрик

Аналитика Службы хранилища Azure поддерживает метрики для Файлов Azure. Данные метрик позволяют отслеживать запросы и диагностировать проблемы.

Вы можете включить метрики для Файлов Azure с помощью портала Azure. Кроме того, вы можете включить метрики программным путем. Для этого вызовите операцию Set File Service Properties через интерфейс REST API или любой ее аналог из имеющихся в клиентской библиотеке Файлов Azure.

В следующем примере кода показано, как использовать клиентскую библиотеку для .NET, чтобы включить метрики для Файлов Azure.

//-------------------------------------------------
// Use metrics
//-------------------------------------------------
public async Task UseMetricsAsync()
{
    // Get the connection string from app settings
    string connectionString = ConfigurationManager.AppSettings["StorageConnectionString"];

    // Instatiate a ShareServiceClient
    ShareServiceClient shareService = new ShareServiceClient(connectionString);

    // Set metrics properties for File service
    await shareService.SetPropertiesAsync(new ShareServiceProperties()
    {
        // Set hour metrics
        HourMetrics = new ShareMetrics()
        {
            Enabled = true,
            IncludeApis = true,
            Version = "1.0",

            RetentionPolicy = new ShareRetentionPolicy()
            {
                Enabled = true,
                Days = 14
            }
        },

        // Set minute metrics
        MinuteMetrics = new ShareMetrics()
        {
            Enabled = true,
            IncludeApis = true,
            Version = "1.0",

            RetentionPolicy = new ShareRetentionPolicy()
            {
                Enabled = true,
                Days = 7
            }
        }
    });

    // Read the metrics properties we just set
    ShareServiceProperties serviceProperties = await shareService.GetPropertiesAsync();

    // Display the properties
    Console.WriteLine();
    Console.WriteLine($"HourMetrics.InludeApis: {serviceProperties.HourMetrics.IncludeApis}");
    Console.WriteLine($"HourMetrics.RetentionPolicy.Days: {serviceProperties.HourMetrics.RetentionPolicy.Days}");
    Console.WriteLine($"HourMetrics.Version: {serviceProperties.HourMetrics.Version}");
    Console.WriteLine();
    Console.WriteLine($"MinuteMetrics.InludeApis: {serviceProperties.MinuteMetrics.IncludeApis}");
    Console.WriteLine($"MinuteMetrics.RetentionPolicy.Days: {serviceProperties.MinuteMetrics.RetentionPolicy.Days}");
    Console.WriteLine($"MinuteMetrics.Version: {serviceProperties.MinuteMetrics.Version}");
    Console.WriteLine();
}

При возникновении каких-либо проблем см. раздел Устранение неполадок Файлы Azure.

Дальнейшие действия

Дополнительные сведения о Файлах Azure см. в перечисленных ниже статьях.

Тематические статьи и видео

Средства для работы с хранилищем файлов

Справочник

Примеры кода, использующие устаревшие пакеты SDK для .NET версии 11.x, см. в статье Примеры кода с использованием .NET версии 11.x.