Files
BetterLyrics/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/FileSystemService/Providers/WebDavFileSystem.cs
Zhe Fang 6ca2d1f897 chores
2025-12-30 19:49:54 -05:00

129 lines
4.4 KiB
C#

using BetterLyrics.WinUI3.Helper;
using BetterLyrics.WinUI3.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using WebDav;
namespace BetterLyrics.WinUI3.Services.FileSystemService.Providers
{
public partial class WebDavFileSystem : IUnifiedFileSystem
{
private readonly WebDavClient _client;
private readonly MediaFolder _config;
private readonly Uri _baseAddress;
public WebDavFileSystem(MediaFolder config)
{
_config = config ?? throw new ArgumentNullException(nameof(config));
// 构建 BaseAddress (只包含 http://host:port/)
// MediaFolder.GetStandardUri() 返回的是带路径的完整 URI (http://host:port/path)
// 提取出根用于初始化 WebDavClient
var fullUri = _config.GetStandardUri();
// 提取 "http://host:port"
_baseAddress = new Uri($"{fullUri.Scheme}://{fullUri.Authority}");
_client = new WebDavClient(new WebDavClientParams
{
BaseAddress = _baseAddress,
Credentials = new System.Net.NetworkCredential(_config.UserName, _config.Password)
});
}
public async Task<bool> ConnectAsync()
{
var result = await _client.Propfind(_config.GetStandardUri().AbsoluteUri);
return result.IsSuccessful;
}
public async Task<List<FilesIndexItem>> GetFilesAsync(FilesIndexItem? parentFolder = null)
{
var list = new List<FilesIndexItem>();
Uri targetUri;
if (parentFolder == null)
{
targetUri = _config.GetStandardUri();
}
else
{
targetUri = new Uri(parentFolder.Uri);
}
var result = await _client.Propfind(targetUri.AbsoluteUri);
if (result.IsSuccessful)
{
string parentUriString = targetUri.AbsoluteUri;
if (!parentUriString.EndsWith("/")) parentUriString += "/";
string targetPathClean = targetUri.AbsolutePath.TrimEnd('/');
foreach (var res in result.Resources)
{
var itemUri = new Uri(_baseAddress, res.Uri);
// 过滤掉文件夹自身
if (itemUri.AbsolutePath.TrimEnd('/') == targetPathClean) continue;
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 FilesIndexItem
{
MediaFolderId = _config.Id,
ParentUri = parentFolder?.Uri ?? _config.GetStandardUri().AbsoluteUri,
Uri = itemUri.AbsoluteUri,
FileName = name,
IsDirectory = res.IsCollection,
FileSize = res.ContentLength ?? 0,
LastModified = res.LastModifiedDate ?? DateTime.MinValue,
});
}
}
return list;
}
public async Task<Stream?> OpenReadAsync(FilesIndexItem entity)
{
if (entity == null) return null;
// WebDAV 获取流,直接使用完整 URI
var res = await _client.GetRawFile(entity.Uri);
if (!res.IsSuccessful)
throw new IOException($"WebDAV Error {res.StatusCode}: {res.Description}");
return res.Stream;
}
public async Task DisconnectAsync() => await Task.CompletedTask;
public void Dispose() => _client?.Dispose();
}
}