Получение последнего измененного файла из Azure Blob

Скажем, я каждый день создаю пару json файлов в своем хранилище BLOB-объектов. Что я хочу сделать, так это изменить последний файл в любом из моих каталогов. Так что у меня будет что-то вроде этого в моем blob:

2016/01/02/test.json
2016/01/02/test2.json
2016/02/03/test.json

Я хочу получить 2016/02/03/test.json. Таким образом, один из способов - получить полный путь к файлу и выполнить проверку регулярного выражения, чтобы найти последний созданный каталог, но это не сработает, если у меня есть более одного файла josn в каждом каталоге. Есть ли что-нибудь вроде File.GetLastWriteTime, чтобы получить последний измененный файл? Я использую эти коды, чтобы получить все файлы, кстати:

public static CloudBlobContainer GetBlobContainer(string accountName, string accountKey, string containerName)
{
    CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
    // blob client
    CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
    // container
    CloudBlobContainer blobContainer = blobClient.GetContainerReference(containerName);
    return blobContainer;
}

public static IEnumerable<IListBlobItem> GetBlobItems(CloudBlobContainer container)
{
    IEnumerable<IListBlobItem> items = container.ListBlobs(useFlatBlobListing: true);
    return items;
}

public static List<string> GetAllBlobFiles(IEnumerable<IListBlobItem> blobs)
{
    var listOfFileNames = new List<string>();

    foreach (var blob in blobs)
    {
        var blobFileName = blob.Uri.Segments.Last();
        listOfFileNames.Add(blobFileName);
    }
    return listOfFileNames;
}

person Yar    schedule 28.03.2016    source источник
comment
наконец, как вы достигли этого сценария для пути к нескольким папкам с последним измененным свойством?   -  person Neo    schedule 29.01.2018
comment
Все текущие ответы устарели для нового пакета nuget Azure blob V12.   -  person rolls    schedule 26.05.2021


Ответы (6)


Каждый IListBlobItem будет CloudBlockBlob, CloudPageBlob или CloudBlobDirectory.

После преобразования в блочный или страничный BLOB-объект или их общий базовый класс CloudBlob (предпочтительно с помощью ключевого слова as и проверки на null) вы можете получить доступ к измененной дате через blockBlob.Properties.LastModified.

Обратите внимание, что ваша реализация выполнит O (n) сканирование всех BLOB-объектов в контейнере, что может занять некоторое время, если есть сотни тысяч файлов. Однако в настоящее время нет способа выполнить более эффективный запрос хранилища BLOB-объектов (если вы не злоупотребляете именованием файлов и не кодируете дату таким образом, чтобы новые даты в алфавитном порядке были первыми). На самом деле, если вам нужна более высокая производительность запросов, я бы рекомендовал держать под рукой таблицу базы данных, которая представляет все списки файлов в виде строк, с такими вещами, как индексированный столбец DateModified для поиска и столбец с путем к blob для легкого доступа к файлу.

person Mike Asdf    schedule 28.03.2016
comment
А как насчет каталогов? как получить доступ к их последнему измененному времени? - person Shmil The Cat; 26.02.2018
comment
Справочники? Вы имеете в виду контейнеры? Или вы имеете в виду конструкцию искусственного ограничителя пути, которую могут иметь имена больших двоичных объектов? - person Mike Asdf; 26.02.2018
comment
Последний (конструкция искусственного ограничителя пути, которую могут иметь имена больших двоичных объектов) - person Shmil The Cat; 26.02.2018
comment
Таким образом, каталог на самом деле представляет собой набор BLOB-объектов, которые имеют определенный строковый префикс, поэтому вам придется перечислить эти BLOB-объекты и агрегировать временные метки BLOB-объектов (по минимальному, максимальному или другому значению в вашей ситуации). Обратите внимание, что фильтрация больших двоичных объектов по префиксу поддерживается API. - person Mike Asdf; 27.02.2018
comment
Во всех остальных ответах не упоминается кастинг - это было очень полезно. - person VSO; 24.01.2019
comment
Это больше не актуально для пакета nuget для Azure V12. - person rolls; 26.05.2021

Как сказал Яр, вы можете использовать свойство LastModified отдельного объекта blob. Вот фрагмент кода, который показывает, как это сделать, если у вас есть ссылка на правильный контейнер:

var latestBlob = container.ListBlobs()
    .OfType<CloudBlockBlob>()
    .OrderByDescending(m => m.Properties.LastModified)
    .ToList()
    .First();

Примечание. Тип BLOB-объекта не может быть <CloudBlockBlob>. Не забудьте изменить это при необходимости.

person hbd    schedule 22.08.2017
comment
Я пытаюсь добиться того же с помощью AZURE FILE SHARE STORAGE, но получаю сообщение об ошибке 'Sequence contains no elements', почему? - person Neo; 27.08.2018
comment
LastModified имеет значение null - person Neo; 27.08.2018

Используйте Azure Web SDK вакансий. В SDK есть опции для отслеживания новых / обновленных больших двоичных объектов.

person viperguynaz    schedule 28.03.2016
comment
Я хочу использовать то же самое для общего файлового хранилища azure, как я могу использовать sdk azure web jobs? - person Neo; 27.08.2018

В случае возникновения проблемы используйте blockBlob.Container.Properties.LastModified

person Prashant N    schedule 10.10.2018

С помощью Microsoft.Azure.Storage.Blob его можно получить как следить:

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Microsoft.Azure.Storage;
using Microsoft.Azure.Storage.Blob;

namespace ListLastModificationOnBlob
{
    class Program
    {
        static void Main(string[] args)
        {
            MainAsync().Wait();
        }

        static async Task MainAsync()
        {
            string storageAccount_connectionString = @"Your connection string";

            // Retrieve storage account from connection string.
            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(storageAccount_connectionString);

            // Create the blob client.
            CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

            var containers = await ListContainersAsync(blobClient);

            foreach (var container in containers)
            {
                Console.WriteLine(container.Name);

                try
                {
                    //root directory
                    CloudBlobDirectory dira = container.GetDirectoryReference(string.Empty);
                    //true for all sub directories else false 
                    var rootDirFolders = dira.ListBlobsSegmentedAsync(true, BlobListingDetails.Metadata, null, null, null, null).Result;

                    using (var w = new StreamWriter($"{container.Name}.csv"))
                    {
                        foreach (var blob in rootDirFolders.Results)
                        {
                            if (blob is CloudBlob blockBlob)
                            {
                                var time = blockBlob.Properties.LastModified;
                                var created = blockBlob.Properties.Created;

                                var line = $"{blockBlob.Name},{created},{time}";
                                await w.WriteLineAsync(line);
                                await w.FlushAsync();
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    //  Block of code to handle errors
                    Console.WriteLine("Error", e);

                }
            }
        }

        private static async Task<IEnumerable<CloudBlobContainer>> ListContainersAsync(CloudBlobClient cloudBlobClient)
        {
            BlobContinuationToken continuationToken = null;
            var containers = new List<CloudBlobContainer>();

            do
            {
                ContainerResultSegment response = await cloudBlobClient.ListContainersSegmentedAsync(continuationToken);
                continuationToken = response.ContinuationToken;
                containers.AddRange(response.Results);

            } while (continuationToken != null);

            return containers;
        }
    }
}

Приведенный выше код для данной учетной записи хранения:

  • получить все контейнеры в Аккаунте
  • взять весь blob-контейнер
  • сохранить Created и LastModified с именем большого двоичного объекта в файле csv (названном как контейнер)
person Krzysztof Madej    schedule 04.09.2020

Предыдущие ответы устарели для нового пакета Nuget V12. Я использовал следующее руководство для обновления с версии 9 до версии 12 https://elcamino.cloud/articles/2020-03-30-azure-storage-blobs-net-sdk-v12-upgrade-guide-and-tips.html

Новый пакет nuget - Azure.Storage.Blobs, и я использовал версию 12.8.4.

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

using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using Azure.Storage.Blobs;
using Azure.Storage.Sas;
using Azure.Storage.Blobs.Specialized;

DateTimeOffset? GetLastModified()
{
    BlobServiceClient blobServiceClient = new BlobServiceClient("connectionstring")
    BlobContainerClient blobContainerClient = blobServiceClient.GetBlobContainerClient("blobname");
    BlobClient blobClient = blobContainerClient.GetBlobClient("file.txt");
    if (blobClient == null || !blobClient.Exists()) return null;
    DateTimeOffset lastModified = blobClient.GetProperties().Value.LastModified;
    return lastModified;
}
person rolls    schedule 26.05.2021
comment
Вопрос OP - получить последний измененный файл, здесь вы просто получаете дату последнего изменения определенного файла? не уверен, как это решает вопрос OP - person user1075613; 02.06.2021
comment
Переберите капли. В основном я пытался показать новый API. - person rolls; 04.06.2021