.NET Framework 4.7 C# 实现Azure Blob通配符匹配增量下载日期分层存储文件
实现方案
核心思路
利用Azure Blob存储原生支持的前缀过滤查询能力,直接跳过LastDateTime之前的所有层级文件夹,无需遍历全量存储内容,从服务端层面减少返回的Blob数量,大幅降低性能开销。
具体实现步骤
步骤1:预处理规则配置
首先从SQL数据库查询所有通配符规则,做如下预处理:
- 把
LastDateTime字段转换为DateTime类型,拆分出年、月、日三个维度的数值 - 提取每条通配符的固定前缀(例如通配符
filetest_*.csv的固定前缀为filetest_),用于后续快速匹配 - 把通配符规则转换为正则表达式,降低文件名匹配的性能消耗
步骤2:按规则生成目标查询前缀
根据每条规则的LastDateTime构造Blob查询前缀,直接定位到需要检索的最小目录范围:
例如规则的LastDateTime为2021-01-01 13:30:35,则查询前缀为2021/01/01/,早于该日期的所有年份、月份、日期目录完全不需要请求访问。
如果有多条规则,可以先合并相同的查询前缀,避免重复请求同一个目录下的Blob列表。如果需要覆盖LastDateTime之后的所有日期,可以生成从该日期到当前系统日期的所有年/月/日前缀,根据实际数据量灵活调整范围。
步骤3:查询Blob并匹配规则
使用Azure Blob SDK for .NET Framework的分段列表查询方法,拉取目标前缀下的所有Blob,仅对返回的Blob做两项校验:
- 文件名匹配对应通配符规则
- 文件名中提取的时间戳大于对应规则的
LastDateTime
满足条件则调用自定义的DownloadFromBlob方法下载文件。
代码示例
首先安装适配.NET Framework 4.7的Blob存储NuGet包:Install-Package Microsoft.Azure.Storage.Blob -Version 11.2.3
using Microsoft.Azure.Storage; using Microsoft.Azure.Storage.Blob; using System; using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; public class BlobDownloader { // 通配符规则实体 public class WildcardRule { public string WildcardPattern { get; set; } public DateTime LastDateTime { get; set; } public Regex PatternRegex { get; set; } } public void DownloadNewFiles(string storageConnectionString, string containerName, List<WildcardRule> rules) { CloudStorageAccount storageAccount = CloudStorageAccount.Parse(storageConnectionString); CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient(); CloudBlobContainer container = blobClient.GetContainerReference(containerName); // 去重存储所有需要查询的前缀 HashSet<string> queryPrefixes = new HashSet<string>(); foreach (var rule in rules) { // 生成规则对应起始日期的前缀 var currentDate = rule.LastDateTime.Date; while (currentDate <= DateTime.Now.Date) { string prefix = $"{currentDate.Year}/{currentDate.Month.ToString("00")}/{currentDate.Day.ToString("00")}/"; queryPrefixes.Add(prefix); currentDate = currentDate.AddDays(1); } } BlobContinuationToken continuationToken = null; foreach (var prefix in queryPrefixes) { do { // 服务端前缀过滤,仅返回该前缀下的Blob,单次最大返回1000条 var resultSegment = container.ListBlobsSegmented(prefix, true, BlobListingDetails.None, 1000, continuationToken, null, null); continuationToken = resultSegment.ContinuationToken; foreach (IListBlobItem item in resultSegment.Results) { if (item is CloudBlockBlob blob) { string fileName = Path.GetFileName(blob.Name); // 按文件名格式提取时间戳,示例格式为filetest_yyyyMMdd_HHmmss.csv string[] nameParts = fileName.Split('_'); if (nameParts.Length >=3 && DateTime.TryParseExact($"{nameParts[1]}_{nameParts[2].Replace(".csv","")}", "yyyyMMdd_HHmmss", null, System.Globalization.DateTimeStyles.None, out DateTime fileTime)) { foreach (var rule in rules) { if (rule.PatternRegex.IsMatch(fileName) && fileTime > rule.LastDateTime) { DownloadFromBlob(blob.Name); // 单文件匹配多规则时按需调整是否重复下载,此处默认匹配到第一条规则后跳出 break; } } } } } } while (continuationToken != null); } } // 通配符转正则的辅助方法 public Regex WildcardToRegex(string pattern) { return new Regex("^" + Regex.Escape(pattern).Replace("\\*", ".*") + "$", RegexOptions.IgnoreCase); } private void DownloadFromBlob(string blobName) { // 自定义下载逻辑实现 } }
额外优化建议
- 如果单天数据量极大,可以进一步拆分查询前缀到小时/分钟维度,进一步减少服务端返回的Blob数量
- 对Blob列表查询结果做本地缓存,避免同一个文件多次匹配规则时重复解析时间戳
- 采用异步方法
ListBlobsSegmentedAsync配合并行下载,提升整体吞吐量
内容的提问来源于stack exchange,提问作者Bradford1138
相关产品推荐
相关产品推荐

