【问题标题】:Getting the latest file modified from Azure Blob从 Azure Blob 获取最新修改的文​​件
【发布时间】:2016-07-15 23:24:07
【问题描述】:

假设我每天在我的 blob 存储中生成几个 json 文件。我想要做的是在我的任何目录中修改最新的文件。所以我的 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;
}

【问题讨论】:

  • 最后你是如何为具有最后修改属性的多个文件夹路径实现这种场景的?
  • 对于新的 V12 azure blob nuget 包,所有当前答案都已过时

标签: c# azure azure-blob-storage azure-sdk-.net


【解决方案1】:

每个 IListBlobItem 将成为 CloudBlockBlob、CloudPageBlob 或 CloudBlobDirectory。

在转换为块或页面 blob 或其共享基类 CloudBlob(最好使用 as 关键字并检查是否为空)后,您可以通过 blockBlob.Properties.LastModified 访问修改日期。

请注意,您的实现将对容器中的所有 blob 进行 O(n) 扫描,如果有数十万个文件,这可能需要一段时间。但是,目前没有办法对 blob 存储进行更有效的查询(除非您滥用文件命名并以新日期按字母顺序排在第一位的方式对日期进行编码)。实际上,如果您需要更好的查询性能,我建议您保留一个方便的数据库表,将所有文件列表表示为行,其中包含要搜索的索引 DateModified 列和带有 blob 路径的列,以便轻松访问文件。

【讨论】:

  • 目录呢?如何访问他们的最后修改时间?
  • 目录?你是说容器吗?还是您的意思是 blob 名称可以具有的人工路径分隔符构造?
  • 后一种(blob 名称可以具有的人工路径分隔符构造)
  • 所以“目录”实际上是共享某个字符串前缀的 blob 集合,因此您必须枚举这些 blob 并聚合 blob 时间戳(按最小值、最大值或任何有意义的值)根据您的情况)。请注意,API 支持通过前缀 过滤 blob。
  • 所有其他答案都没有提到铸造 - 这非常有帮助。
【解决方案2】:

就像 Yar 所说,您可以使用单个 blob 对象的 LastModified 属性。这是一个代码 sn-p 显示如何执行此操作,一旦您引用了正确的容器:

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

注意:blob 类型可能不是&lt;CloudBlockBlob&gt;。如有必要,请务必更改。

【讨论】:

  • 我正在尝试使用 AZURE FILE SHARE STORAGE 实现相同的目标,但收到错误 'Sequence contains no elements' 任何线索为什么?
  • LastModified 为空
【解决方案3】:
       //connection string
        string storageAccount_connectionString = "**NOTE: CONNECTION STRING**";

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

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

        // Retrieve reference to a previously created container.
        CloudBlobContainer container = blobClient.GetContainerReference("**NOTE:NAME OF CONTAINER**");
        //The specified container does not exist

        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;

            foreach (var blob in rootDirFolders.Results)
            {
                if (blob is CloudBlockBlob blockBlob)

                {
                    var time = blockBlob.Properties.LastModified;
                    Console.WriteLine("Data", time);

                }
            }

        }
        catch (Exception e)
        {
            //  Block of code to handle errors
            Console.WriteLine("Error", e);

        }

【讨论】:

    【解决方案4】:

    使用Azure Web Jobs SDK。 SDK 具有监控新/更新 BLOB 的选项。

    【讨论】:

    • 我想在 azure 文件共享存储中使用相同的内容,如何使用 azure web jobs sdk?
    【解决方案5】:

    如有问题请使用blockBlob.Container.Properties.LastModified

    【讨论】:

      【解决方案6】:

      对于新的 V12 Nuget 包,以前的答案已经过时。我使用以下指南帮助从版本 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;
      }
      

      【讨论】:

      • OP 问题是获取最新修改的文​​件,这里你只是获取特定文件的最后修改日期?不确定它如何解决 OP 问题
      • 遍历 blob。我主要是想展示新的 API。
      【解决方案7】:

      使用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 都作为容器
      • CreatedLastModified 与 blob 名称保存在 csv 文件中(命名为容器)

      【讨论】:

        猜你喜欢
        • 2018-07-08
        • 1970-01-01
        • 2019-04-06
        • 1970-01-01
        • 2021-02-06
        • 2022-01-13
        • 1970-01-01
        • 2017-03-09
        • 2021-11-16
        相关资源
        最近更新 更多