From 0787f5b111638aa8bbd9201ccd3478f5352688f8 Mon Sep 17 00:00:00 2001 From: Zhe Fang Date: Sun, 28 Dec 2025 21:10:02 -0500 Subject: [PATCH] fix --- .../Providers/SMBFileSystem.cs | 28 +++---------- .../Providers/WebDavFileSystem.cs | 40 ++++++++----------- 2 files changed, 22 insertions(+), 46 deletions(-) diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/FileSystemService/Providers/SMBFileSystem.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/FileSystemService/Providers/SMBFileSystem.cs index c4992ac..ea9c7f4 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/FileSystemService/Providers/SMBFileSystem.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/FileSystemService/Providers/SMBFileSystem.cs @@ -15,7 +15,7 @@ namespace BetterLyrics.WinUI3.Services.FileSystemService.Providers private SMB2Client? _client; private ISMBFileStore? _fileStore; - // 保存配置对象的引用,它是我们的“真理来源” + // 保存配置对象的引用 private readonly MediaFolder _config; // 缓存解析出来的 Share 名称,因为 TreeConnect 要用 @@ -26,8 +26,6 @@ namespace BetterLyrics.WinUI3.Services.FileSystemService.Providers _config = config ?? throw new ArgumentNullException(nameof(config)); // 在构造时就解析好 Share 名称,避免后续重复解析 - // 假设 URI 是 smb://host/ShareName/Folder/Sub - // 我们需要提取 "ShareName" var uri = _config.GetStandardUri(); // Segments[0] 是 "/", Segments[1] 是 "ShareName/" @@ -48,16 +46,16 @@ namespace BetterLyrics.WinUI3.Services.FileSystemService.Providers { _client = new SMB2Client(); - // 1. 连接主机 + // 连接主机 bool connected = _client.Connect(_config.UriHost, SMBTransportType.DirectTCPTransport); if (!connected) return false; - // 2. 登录 + // 登录 var status = _client.Login(string.Empty, _config.UserName, _config.Password); if (status != NTStatus.STATUS_SUCCESS) return false; - // 3. 连接共享目录 (TreeConnect) - // 注意:SMBLibrary 必须先连接到 Share,后续所有文件操作都是基于这个 Share 的相对路径 + // 连接共享目录 (TreeConnect) + // SMBLibrary 必须先连接到 Share,后续所有文件操作都是基于这个 Share 的相对路径 if (string.IsNullOrEmpty(_shareName)) return false; _fileStore = _client.TreeConnect(_shareName, out status); @@ -161,7 +159,6 @@ namespace BetterLyrics.WinUI3.Services.FileSystemService.Providers { if (_fileStore == null || file == null) return null; - // ★ 核心简化:直接把对象扔进去,获取路径 string smbPath = GetPathRelativeToShare(file); var ret = _fileStore.CreateFile(out object handle, out FileStatus status, smbPath, @@ -184,9 +181,6 @@ namespace BetterLyrics.WinUI3.Services.FileSystemService.Providers _client?.Disconnect(); } - // ========================================================= - // ★ 私有魔法方法:处理所有令人头大的路径逻辑 - // ========================================================= private string GetPathRelativeToShare(FileCacheEntity? entity) { Uri targetUri; @@ -200,29 +194,17 @@ namespace BetterLyrics.WinUI3.Services.FileSystemService.Providers targetUri = new Uri(entity.Uri); } - // 1. 获取绝对路径 - // ★★★ 关键修正:必须解码!把 %20 变回空格 ★★★ - // targetUri.AbsolutePath -> "/Share/My%20Music/Song.mp3" - // Uri.UnescapeDataString -> "/Share/My Music/Song.mp3" string absolutePath = Uri.UnescapeDataString(targetUri.AbsolutePath); - - // 2. 移除 ShareName 部分 - // 确保移除开头的 / string cleanPath = absolutePath.TrimStart('/'); - - // 找到 ShareName 后的第一个斜杠 int slashIndex = cleanPath.IndexOf('/'); if (slashIndex == -1) { - // 如果没有斜杠,说明就是 Share 根目录 return string.Empty; } - // 截取 Share 之后的部分 string relativePath = cleanPath.Substring(slashIndex + 1); - // 3. 转换为 Windows 风格的反斜杠 (SMB 协议要求) return relativePath.Replace("/", "\\"); } } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/FileSystemService/Providers/WebDavFileSystem.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/FileSystemService/Providers/WebDavFileSystem.cs index 6bf9c3c..bb67d8a 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/FileSystemService/Providers/WebDavFileSystem.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/FileSystemService/Providers/WebDavFileSystem.cs @@ -1,4 +1,5 @@ -using BetterLyrics.WinUI3.Models; +using BetterLyrics.WinUI3.Helper; +using BetterLyrics.WinUI3.Models; using System; using System.Collections.Generic; using System.IO; @@ -18,9 +19,9 @@ namespace BetterLyrics.WinUI3.Services.FileSystemService.Providers { _config = config ?? throw new ArgumentNullException(nameof(config)); - // 1. 构建 BaseAddress (只包含 http://host:port/) + // 构建 BaseAddress (只包含 http://host:port/) // MediaFolder.GetStandardUri() 返回的是带路径的完整 URI (http://host:port/path) - // 我们需要提取出根用于初始化 WebDavClient + // 提取出根用于初始化 WebDavClient var fullUri = _config.GetStandardUri(); // 提取 "http://host:port" @@ -52,7 +53,6 @@ namespace BetterLyrics.WinUI3.Services.FileSystemService.Providers { var list = new List(); - // 1. 确定目标 URI Uri targetUri; if (parentFolder == null) { @@ -63,60 +63,54 @@ namespace BetterLyrics.WinUI3.Services.FileSystemService.Providers targetUri = new Uri(parentFolder.Uri); } - // 2. 发送请求 (使用绝对 URI) - // WebDavClient 允许传入绝对路径,它会自动处理 var result = await _client.Propfind(targetUri.AbsoluteUri); if (result.IsSuccessful) { - // 3. 准备父级 URI 字符串 (用于填充 Entity) - // 确保以 / 结尾,方便后续逻辑判断或数据库查询 string parentUriString = targetUri.AbsoluteUri; if (!parentUriString.EndsWith("/")) parentUriString += "/"; - // WebDAV 可能会把文件夹自己作为结果返回,我们需要过滤它 - // 比较时忽略末尾斜杠 string targetPathClean = targetUri.AbsolutePath.TrimEnd('/'); foreach (var res in result.Resources) { - // res.Uri 通常是相对路径,例如 "/dav/music/file.mp3" - // 我们需要将其转换为绝对 URI var itemUri = new Uri(_baseAddress, res.Uri); - // ★ 过滤掉文件夹自身 - // 比较 AbsolutePath (例如 /dav/music vs /dav/music) + // 过滤掉文件夹自身 if (itemUri.AbsolutePath.TrimEnd('/') == targetPathClean) continue; - // 获取文件名 (解码) - // res.DisplayName 有时候是空的,这时候需要从 Uri 解析 - string name = res.DisplayName; + string? name = res.DisplayName; if (string.IsNullOrEmpty(name)) { - // 取最后一段,忽略末尾斜杠 name = itemUri.AbsolutePath.TrimEnd('/').Split('/').Last(); name = System.Net.WebUtility.UrlDecode(name); } if (string.IsNullOrEmpty(name)) continue; + if (name.StartsWith(".")) continue; + + bool isDir = res.IsCollection; + if (!isDir) + { + string extension = System.IO.Path.GetExtension(name); + // 如果后缀为空或不在白名单,跳过 + if (string.IsNullOrEmpty(extension) || !FileHelper.AllSupportedExtensions.Contains(extension)) continue; + } + list.Add(new FileCacheEntity { MediaFolderId = _config.Id, - // 记录父级 URI (保持传入时的形式,或者统一标准) - // 注意:对于 WebDAV,ParentUri 最好不带末尾斜杠,除非是根 ParentUri = parentFolder?.Uri ?? _config.GetStandardUri().AbsoluteUri, - // ★ 存储完整的 http://... 标准 URI Uri = itemUri.AbsoluteUri, FileName = name, IsDirectory = res.IsCollection, - // WebDAV 通常能提供这些信息 FileSize = res.ContentLength ?? 0, - LastModified = res.LastModifiedDate + LastModified = res.LastModifiedDate ?? DateTime.MinValue, }); } }