From e2a1da8500b0442cc16a36e73ebf4dfe0fbc7818 Mon Sep 17 00:00:00 2001 From: SALTWOOD <105980161+SALTWOOD@users.noreply.github.com> Date: Sun, 19 May 2024 16:02:02 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20WebDavClient=20=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Network/WebDav/WebDavClient.cs | 101 ++++++++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 2 deletions(-) diff --git a/Network/WebDav/WebDavClient.cs b/Network/WebDav/WebDavClient.cs index ff45d89..9ab6921 100644 --- a/Network/WebDav/WebDavClient.cs +++ b/Network/WebDav/WebDavClient.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; using System.Web; +using System.Xml.Linq; namespace TeraIO.Network.WebDav { @@ -34,6 +36,17 @@ public async Task PutFile(string fileName, byte[] data) return await this.httpClient.PutAsync(fileName, content); } + public async Task PutFile(string fileName, Stream stream) + { + HttpContent content = new StreamContent(stream); + if (!string.IsNullOrWhiteSpace(lockToken)) + { + content.Headers.Add("Lock-Token", lockToken); + content.Headers.Add("If", $"({lockToken})"); + } + return await this.httpClient.PutAsync(fileName, content); + } + public async Task CreateFolder(string folderName) { return await this.httpClient.SendAsync(new HttpRequestMessage(new HttpMethod("MKCOL"), folderName)); @@ -44,12 +57,86 @@ public async Task Exists(string name) return (await this.httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, name))).IsSuccessStatusCode; } + public async Task GetFileSize(string name) + { + var resp = await this.httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, name)); + if (!resp.IsSuccessStatusCode) + { + return 0; + } + if (resp.Content.Headers.TryGetValues("Content-Length", out var fileSize)) + { + return long.Parse(fileSize.First()); + } + return 0; + } + + public async Task> ListFilesAndFolders(string folderPath, int depth = -1) + { + var requestMessage = new HttpRequestMessage(new HttpMethod("PROPFIND"), folderPath) + { + Headers = + { + { "Depth", depth.ToString() } + }, + Content = new StringContent(string.Empty) + }; + if (depth < 0) + { + requestMessage.Headers.Remove("Depth"); + } + requestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/xml"); + + var response = await httpClient.SendAsync(requestMessage); + response.EnsureSuccessStatusCode(); + + var responseContent = await response.Content.ReadAsStringAsync(); + return ParsePropFindResponse(responseContent); + } + + private List ParsePropFindResponse(string responseContent) + { + XDocument document = XDocument.Parse(responseContent); + XNamespace ns = "DAV:"; + + List items = new List(); + + foreach (var response in document.Descendants(ns + "response")) + { + var hrefElement = response.Element(ns + "href"); + if (hrefElement != null) + { + items.Add(hrefElement.Value); + } + } + + return items; + } + public string GetFileDownloadLink(string filePath) { - //TODO: GetFileDownloadLink - throw new NotImplementedException("TODO: GetFileDownloadLink"); + // Ensure the file path is correctly URL encoded + string encodedFilePath = HttpUtility.UrlEncode(filePath); + + // Construct the full URL for downloading the file + string url = $"{httpClient.BaseAddress}{encodedFilePath}"; + + // Determine if the URL should use https or http + string protocol = url.StartsWith("https", StringComparison.OrdinalIgnoreCase) ? "https" : "http"; + + // Check the Authorization header for Basic auth and modify the URL accordingly + if (httpClient.DefaultRequestHeaders.Authorization != null && + httpClient.DefaultRequestHeaders.Authorization.Scheme.Equals("Basic", StringComparison.OrdinalIgnoreCase)) + { + string? authPart = httpClient.DefaultRequestHeaders.Authorization.Parameter; + string authContents = Encoding.UTF8.GetString(Convert.FromBase64String(authPart ?? "")); + url = url.Replace($"{protocol}://", $"{protocol}://{authContents}@"); + } + + return url; } + public async Task Delete(string name) { return await this.httpClient.DeleteAsync(name); @@ -67,6 +154,16 @@ public async Task Lock(string name, int timeout = 60) return response; } + public async Task GetFile(string filename) + { + return await (await this.httpClient.GetAsync(filename)).Content.ReadAsByteArrayAsync(); + } + + public async Task GetFileStream(string filename) + { + return await (await this.httpClient.GetAsync(filename)).Content.ReadAsStreamAsync(); + } + public async Task Unlock(string name) { HttpRequestMessage message = new HttpRequestMessage(new HttpMethod("UNLOCK"), name);