You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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做两项校验:

  1. 文件名匹配对应通配符规则
  2. 文件名中提取的时间戳大于对应规则的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 23:06:04