C#实现获取基础URL下所有子目录文件的绝对URL
如何遍历目录列表获取所有子目录中的日志文件绝对URL
原代码问题分析
- URL拼接错误:手动拼接
rootUrl + match.Groups["log"]无法正确处理相对路径(比如子目录中的./file.log或上级目录的../file.log),会生成无效URL。 - 正则匹配局限性:原正则依赖特定前置文本(如
[0-9]或dir),目录列表HTML结构稍有变化就会匹配失败。 - 文件收集逻辑分散:文件被存在目录节点的子列表中,无法直接获取全局的所有文件URL列表。
修改后的完整实现
using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Text.RegularExpressions; class Program { static void Main() { // 存储所有日志文件的绝对URL List<string> allLogFiles = new List<string>(); TraverseDirectory("http://example/", allLogFiles); // 输出结果 foreach (var fileUrl in allLogFiles) { Console.WriteLine(fileUrl); } } /// <summary> /// 递归遍历目录列表,收集所有日志文件URL /// </summary> /// <param name="currentUrl">当前要遍历的目录URL</param> /// <param name="logFiles">存储结果的列表</param> private static void TraverseDirectory(string currentUrl, List<string> logFiles) { string html = ReadHtmlContentFromUrl(currentUrl); Uri currentUri = new Uri(currentUrl.TrimEnd('/') + "/"); // 匹配所有<a>标签中的href属性,适配常见目录列表格式 Regex linkRegex = new Regex(@"<a\s+href=""(?<href>[^""]+)""", RegexOptions.IgnoreCase); MatchCollection matches = linkRegex.Matches(html); foreach (Match match in matches) { if (!match.Success) continue; string relativePath = match.Groups["href"].Value; // 跳过上级目录链接和当前目录链接 if (relativePath == "." || relativePath == "..") continue; // 组合成绝对URL Uri absoluteUri = new Uri(currentUri, relativePath); string absoluteUrl = absoluteUri.ToString(); // 判断是否为目录:目录URL通常以/结尾,或者从HTML文本中判断(比如包含"[DIR]"字样) bool isDirectory = absoluteUrl.EndsWith("/") || html.Contains($"<a href=\"{relativePath}\".*?dir"); if (isDirectory) { // 递归遍历子目录 TraverseDirectory(absoluteUrl, logFiles); } else { // 只收集日志文件(后缀为.log) if (absoluteUrl.EndsWith(".log", StringComparison.OrdinalIgnoreCase)) { logFiles.Add(absoluteUrl); } } } } /// <summary> /// 从URL读取HTML内容 /// </summary> private static string ReadHtmlContentFromUrl(string url) { try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) using (Stream stream = response.GetResponseStream()) using (StreamReader reader = new StreamReader(stream)) { return reader.ReadToEnd(); } } catch (WebException ex) { Console.WriteLine($"访问URL失败: {url}, 错误: {ex.Message}"); return string.Empty; } } }
关键修改说明
- 安全的URL组合:使用
new Uri(currentUri, relativePath)自动处理相对路径,确保生成的绝对URL始终有效,适配子目录、上级目录等复杂路径场景。 - 通用的正则匹配:简化正则表达式,直接匹配所有
<a>标签的href属性,摆脱对特定前置文本的依赖,兼容更多目录列表格式。 - 目录判断逻辑:通过URL是否以
/结尾,结合HTML中的目录标识(如dir关键字)判断目录,兼容性更强。 - 直接收集文件:用全局列表存储所有日志文件URL,无需嵌套结构,直接获取最终结果。
- 错误处理:增加WebException捕获,避免单个目录访问失败导致整个遍历终止。
额外优化建议
- 可添加并发遍历(使用Task)提升效率,注意控制并发量避免对服务器造成压力。
- 增加缓存机制,避免重复访问同一目录。
- 支持配置文件后缀过滤,适配多种日志格式(如
.txt、.log.gz等)。
内容的提问来源于stack exchange,提问作者Karmesh Duggar
相关产品推荐
相关产品推荐

