BS 0.0.1 Update Web

This commit is contained in:
ninemine
2025-06-29 16:51:35 +08:00
parent 981157dfec
commit c0ee2d12e1

View File

@@ -1,61 +1,23 @@
using UnityEngine;
using UnityEngine.Networking;
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text.RegularExpressions; using System.Net.Http;
using Newtonsoft; using System.Text;
using Newtonsoft.Json; using System.Text.Json;
using System.Threading.Tasks;
namespace Convention namespace Convention
{ {
[Serializable] [Serializable]
public class ToolURL : LeftValueReference<string> public sealed class ToolURL
#if UNITY_EDITOR
, ISerializationCallbackReceiver
#endif
{ {
[System.AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = false)] private string url;
public class URLAttribute : Attribute private static readonly HttpClient httpClient = new();
{ private object data;
public string[] urlTypes;
public URLAttribute(params string[] types)
{
urlTypes = types;
}
public URLAttribute(bool IsAnyURL)
{
if (IsAnyURL)
urlTypes = new string[] { "*" };
else
urlTypes = new string[] { };
}
}
public static string[] ImageURLTypes = new string[] { "jpg", "jpeg", "png", "gif", "bmp", "webp" }; public ToolURL(string url)
public static string[] AudioURLTypes = new string[] { "mp3", "wav", "ogg", "aac", "m4a" };
public static string[] VideoURLTypes = new string[] { "mp4", "webm", "mov", "avi", "mkv" };
public static string[] DocumentURLTypes = new string[] { "pdf", "doc", "docx", "txt", "rtf" };
public static string[] JsonURLTypes = new string[] { "json" };
[Content, SerializeField] private string url { get => ref_value; set => ref_value = value; }
[Ignore][HideInInspector] public UnityWebRequest WebRequest { get; protected set; }
[Content] public object data;
public ToolURL([In] string url) : base(url) { }
~ToolURL()
{ {
this.Close(); this.url = url;
}
public override string SymbolName()
{
return
$"url<" +
$"{(IsValid ? "v" : "-")}" +
$">";
} }
public override string ToString() public override string ToString()
@@ -63,89 +25,67 @@ namespace Convention
return this.url; return this.url;
} }
public delegate void GetCallback([In] UnityWebRequest request); #region HTTP Methods
public bool Get([In] GetCallback callback)
public async Task<bool> GetAsync(Action<HttpResponseMessage> callback)
{ {
if (!IsValid) if (!IsValid)
return false; return false;
WebRequest = UnityWebRequest.Get(this.url); try
WebRequest.SendWebRequest();
while (!WebRequest.isDone) ;
callback(WebRequest);
return WebRequest.result == UnityWebRequest.Result.Success;
}
public delegate void GetAsyncCallback([In, Opt] UnityWebRequest request);
public IEnumerator GetAsync([In] GetAsyncCallback callback)
{ {
if (!IsValid) var response = await httpClient.GetAsync(this.url);
callback(response);
return response.IsSuccessStatusCode;
}
catch
{ {
callback(null); callback(null);
yield break; return false;
}
} }
WebRequest = UnityWebRequest.Get(this.url); public bool Get(Action<HttpResponseMessage> callback)
WebRequest.SendWebRequest(); {
return GetAsync(callback).GetAwaiter().GetResult();
while (!WebRequest.isDone)
yield return null;
callback(WebRequest);
} }
public delegate void PostCallback([In] UnityWebRequest request); public async Task<bool> PostAsync(Action<HttpResponseMessage> callback, Dictionary<string, string> formData = null)
public delegate UnityWebRequest PostIniter([In]UnityWebRequest request);
public bool Post([In] PostCallback callback, [In]WWWForm form)
{ {
if (!IsValid) if (!IsValid)
return false; return false;
WebRequest = UnityWebRequest.Post(this.url, form); try
WebRequest.SendWebRequest();
while (!WebRequest.isDone) ;
callback(WebRequest);
return WebRequest.result == UnityWebRequest.Result.Success;
}
public bool Post([In]PostCallback callback, [In]PostIniter initer, [In]WWWForm form)
{ {
if (!IsValid) HttpContent content = null;
return false; if (formData != null)
{
WebRequest = initer(UnityWebRequest.Post(this.url, form)); content = new FormUrlEncodedContent(formData);
WebRequest.SendWebRequest();
while (!WebRequest.isDone) ;
callback(WebRequest);
return WebRequest.result == UnityWebRequest.Result.Success;
} }
public delegate void PostAsyncCallback([In, Opt] UnityWebRequest request); var response = await httpClient.PostAsync(this.url, content);
public IEnumerator PostAsync([In] PostAsyncCallback callback, [In] WWWForm form) callback(response);
{ return response.IsSuccessStatusCode;
if (!IsValid) }
catch
{ {
callback(null); callback(null);
yield break; return false;
}
} }
WebRequest = UnityWebRequest.Post(this.url, form); public bool Post(Action<HttpResponseMessage> callback, Dictionary<string, string> formData = null)
WebRequest.SendWebRequest(); {
return PostAsync(callback, formData).GetAwaiter().GetResult();
while (!WebRequest.isDone)
yield return null;
callback(WebRequest);
} }
#endregion
#region URL Properties #region URL Properties
public string FullURL => this.url; public string FullURL => this.url;
public static implicit operator string(ToolURL data) => data.FullURL; public static implicit operator string(ToolURL data) => data.FullURL;
public string GetFullURL() public string GetFullURL()
{ {
return this.url; return this.url;
@@ -179,10 +119,13 @@ namespace Convention
return true; return true;
return false; return false;
} }
#endregion #endregion
#region Validation #region Validation
public bool IsValid => ValidateURL(); public bool IsValid => ValidateURL();
public bool ValidateURL() public bool ValidateURL()
{ {
if (string.IsNullOrEmpty(this.url)) if (string.IsNullOrEmpty(this.url))
@@ -191,451 +134,174 @@ namespace Convention
return Uri.TryCreate(this.url, UriKind.Absolute, out Uri uriResult) return Uri.TryCreate(this.url, UriKind.Absolute, out Uri uriResult)
&& (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps); && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps);
} }
public static implicit operator bool(ToolURL url) => url.IsValid; public static implicit operator bool(ToolURL url) => url.IsValid;
#endregion #endregion
public ToolURL Refresh() #region Load Methods
{
this.Close();
return this;
}
public static object LoadObjectFromBinary([In] byte[] data) public async Task<string> LoadAsTextAsync()
{ {
using MemoryStream fs = new(data, false); if (!IsValid)
return new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter().Deserialize(fs); return null;
}
public ToolURL Data2Object()
{
this.data = LoadObjectFromBinary((byte[])this.data);
return this;
}
public ToolURL Data2Bytes()
{
using MemoryStream ms = new();
new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter().Serialize(ms, this.data);
var outdata = ms.GetBuffer();
this.data = outdata;
return this;
}
public bool IsDataByteArray()
{
return this.data != null && this.data.GetType() == typeof(byte[]);
}
#region Load
public object Load()
{
if (IsText)
return this.LoadAsText();
else if (IsJson)
return LoadAsJson();
else if (IsImage)
return LoadAsImage();
else if (IsAudio)
return LoadAsAudio();
else if (IsDocument)
return LoadAsDocument();
else
return LoadAsText();
}
public static T LoadFromText<T>([In] string requestText)
{
return JsonConvert.DeserializeObject<T>(requestText);
}
[return: ReturnMayNull]
public static T LoadFromRequest<T>([In] UnityWebRequest request)
{
while (!request.isDone) ;
return request.result == UnityWebRequest.Result.Success
? LoadFromText<T>(request.downloadHandler.text)
: default;
}
[return: ReturnNotNull]
public static T LoadFromRequestNotNull<T>([In] UnityWebRequest request) where T : class, new()
{
while (!request.isDone) ;
return request.result == UnityWebRequest.Result.Success
? LoadFromText<T>(request.downloadHandler.text)
: new();
}
[return: ReturnMayNull]
public static IEnumerator LoadFromRequestAsync<T>([In] UnityWebRequest request,[In]Action<T> callback)
{
while (!request.isDone)
{
yield return null;
}
callback(request.result == UnityWebRequest.Result.Success
? LoadFromText<T>(request.downloadHandler.text)
: default);
}
[return: ReturnNotNull]
public static IEnumerator LoadFromRequestNotNullAsync<T>([In] UnityWebRequest request, [In] Action<T> callback) where T : class, new()
{
while (!request.isDone)
{
yield return null;
}
callback(request.result == UnityWebRequest.Result.Success
? LoadFromText<T>(request.downloadHandler.text)
: new());
}
public object LoadAsJson()
{
return LoadAsJsonWithType<object>();
}
public T LoadAsJsonWithType<T>()
{
string jsonText = LoadAsText();
try try
{ {
T result = JsonConvert.DeserializeObject<T>(jsonText); var response = await httpClient.GetAsync(this.url);
this.data = result; if (response.IsSuccessStatusCode)
return result;
}
catch (Exception)
{ {
Debug.Log(jsonText); this.data = await response.Content.ReadAsStringAsync();
return default; return (string)this.data;
} }
} }
catch
{
// 请求失败
}
public T LoadAsJsonWithType<T>(T whenThrow) return null;
{
string jsonText = LoadAsText();
try
{
T result = JsonConvert.DeserializeObject<T>(jsonText);
this.data = result;
return result;
}
catch (Exception)
{
Debug.Log(jsonText);
return whenThrow;
}
} }
public string LoadAsText() public string LoadAsText()
{
return LoadAsTextAsync().GetAwaiter().GetResult();
}
public async Task<byte[]> LoadAsBinaryAsync()
{ {
if (!IsValid) if (!IsValid)
return null; return null;
WebRequest = UnityWebRequest.Get(this.url); try
WebRequest.SendWebRequest();
while (!WebRequest.isDone)
{ {
// 等待请求完成 var response = await httpClient.GetAsync(this.url);
if (response.IsSuccessStatusCode)
{
this.data = await response.Content.ReadAsByteArrayAsync();
return (byte[])this.data;
} }
}
if (WebRequest.result == UnityWebRequest.Result.Success) catch
{ {
this.data = WebRequest.downloadHandler.text; // 请求失败
return (string)this.data;
} }
return null; return null;
} }
public IEnumerator LoadAsTextAsync([In] Action<string> callback)
{
if (!IsValid)
{
callback(null);
yield break;
}
WebRequest = UnityWebRequest.Get(this.url);
yield return WebRequest.SendWebRequest();
if (WebRequest.result == UnityWebRequest.Result.Success)
{
this.data = WebRequest.downloadHandler.text;
callback((string)this.data);
}
else
{
callback(null);
}
}
public byte[] LoadAsBinary() public byte[] LoadAsBinary()
{ {
if (!IsValid) return LoadAsBinaryAsync().GetAwaiter().GetResult();
return null; }
WebRequest = UnityWebRequest.Get(this.url); public T LoadAsJson<T>()
WebRequest.SendWebRequest();
while (!WebRequest.isDone)
{ {
// 等待请求完成 string jsonText = LoadAsText();
} if (string.IsNullOrEmpty(jsonText))
return default(T);
if (WebRequest.result == UnityWebRequest.Result.Success) try
{ {
this.data = WebRequest.downloadHandler.data; T result = JsonSerializer.Deserialize<T>(jsonText);
return (byte[])this.data; this.data = result;
return result;
} }
catch
return null;
}
public IEnumerator LoadAsBinaryAsync([In] Action<byte[]> callback)
{ {
if (!IsValid) return default(T);
}
}
public async Task<T> LoadAsJsonAsync<T>()
{ {
callback(null); string jsonText = await LoadAsTextAsync();
yield break; if (string.IsNullOrEmpty(jsonText))
} return default(T);
WebRequest = UnityWebRequest.Get(this.url); try
yield return WebRequest.SendWebRequest();
if (WebRequest.result == UnityWebRequest.Result.Success)
{ {
this.data = WebRequest.downloadHandler.data; T result = JsonSerializer.Deserialize<T>(jsonText);
callback((byte[])this.data); this.data = result;
return result;
} }
else catch
{ {
callback(null); return default(T);
} }
} }
public Texture2D LoadAsImage()
{
if (!IsValid)
return null;
WebRequest = UnityWebRequestTexture.GetTexture(this.url);
WebRequest.SendWebRequest();
while (!WebRequest.isDone)
{
// 等待请求完成
}
if (WebRequest.result == UnityWebRequest.Result.Success)
{
this.data = DownloadHandlerTexture.GetContent(WebRequest);
return (Texture2D)this.data;
}
return null;
}
public IEnumerator LoadAsImageAsync([In] Action<Texture2D> callback)
{
if (!IsValid)
{
callback(null);
yield break;
}
WebRequest = UnityWebRequestTexture.GetTexture(this.url);
yield return WebRequest.SendWebRequest();
if (WebRequest.result == UnityWebRequest.Result.Success)
{
this.data = DownloadHandlerTexture.GetContent(WebRequest);
callback((Texture2D)this.data);
}
else
{
callback(null);
}
}
public AudioClip LoadAsAudio()
{
if (!IsValid)
return null;
WebRequest = UnityWebRequestMultimedia.GetAudioClip(this.url, GetAudioType());
WebRequest.SendWebRequest();
while (!WebRequest.isDone)
{
// 等待请求完成
}
if (WebRequest.result == UnityWebRequest.Result.Success)
{
this.data = DownloadHandlerAudioClip.GetContent(WebRequest);
return (AudioClip)this.data;
}
return null;
}
public IEnumerator LoadAsAudioAsync([In] Action<AudioClip> callback)
{
if (!IsValid)
{
callback(null);
yield break;
}
WebRequest = UnityWebRequestMultimedia.GetAudioClip(this.url, GetAudioType());
yield return WebRequest.SendWebRequest();
if (WebRequest.result == UnityWebRequest.Result.Success)
{
this.data = DownloadHandlerAudioClip.GetContent(WebRequest);
callback((AudioClip)this.data);
}
else
{
callback(null);
}
}
public byte[] LoadAsDocument()
{
return LoadAsBinary();
}
public IEnumerator LoadAsDocumentAsync([In] Action<byte[]> callback)
{
yield return LoadAsBinaryAsync(callback);
}
public object LoadAsUnknown()
{
this.data = this.LoadAsBinary();
return this;
}
#endregion #endregion
#region Save #region Save Methods
public void Save([In][Opt] string localPath = null)
public void Save(string localPath = null)
{ {
if (IsText) if (IsText)
SaveAsText(localPath); SaveAsText(localPath);
else if (IsJson) else if (IsJson)
SaveAsJson(localPath); SaveAsJson(localPath);
else if (IsImage)
SaveAsImage(localPath);
else if (IsAudio)
SaveAsAudio(localPath);
else if (IsVideo)
SaveAsVideo(localPath);
else if (IsDocument)
SaveAsDocument(localPath);
else else
SaveAsBinary(localPath); SaveAsBinary(localPath);
} }
public void SaveAsJson([In][Opt] string localPath = null) public void SaveAsText(string localPath = null)
{ {
if (localPath == null) if (localPath == null)
{ {
localPath = Path.Combine(Application.temporaryCachePath, GetFilename()); localPath = Path.Combine(Path.GetTempPath(), GetFilename());
} }
string jsonText = JsonConvert.SerializeObject(this.data); if (this.data is string text)
{
File.WriteAllText(localPath, text);
}
}
public void SaveAsJson(string localPath = null)
{
if (localPath == null)
{
localPath = Path.Combine(Path.GetTempPath(), GetFilename());
}
if (this.data != null)
{
string jsonText = JsonSerializer.Serialize(this.data);
File.WriteAllText(localPath, jsonText); File.WriteAllText(localPath, jsonText);
} }
}
public void SaveAsText([In][Opt] string localPath = null) public void SaveAsBinary(string localPath = null)
{ {
if (localPath == null) if (localPath == null)
{ {
localPath = Path.Combine(Application.temporaryCachePath, GetFilename()); localPath = Path.Combine(Path.GetTempPath(), GetFilename());
} }
File.WriteAllText(localPath, (string)this.data); if (this.data is byte[] bytes)
}
public void SaveAsBinary([In][Opt] string localPath = null)
{ {
if (localPath == null)
{
localPath = Path.Combine(Application.temporaryCachePath, GetFilename());
}
File.WriteAllBytes(localPath, (byte[])this.data);
}
public void SaveAsImage([In][Opt] string localPath = null)
{
if (localPath == null)
{
localPath = Path.Combine(Application.temporaryCachePath, GetFilename());
}
Texture2D texture = (Texture2D)this.data;
byte[] bytes = texture.EncodeToPNG();
File.WriteAllBytes(localPath, bytes); File.WriteAllBytes(localPath, bytes);
} }
public void SaveAsAudio([In][Opt] string localPath = null)
{
// 注意Unity不直接支持将AudioClip保存为文件
// 这里只是一个示例,实际应用中可能需要其他方法
Debug.LogWarning("Direct saving of AudioClip to file is not supported in Unity");
} }
public void SaveAsVideo([In][Opt] string localPath = null)
{
// 注意Unity不直接支持将VideoClip保存为文件
// 这里只是一个示例,实际应用中可能需要其他方法
Debug.LogWarning("Direct saving of VideoClip to file is not supported in Unity");
}
public void SaveAsDocument([In][Opt] string localPath = null)
{
SaveAsBinary(localPath);
}
#endregion #endregion
public static AudioType GetAudioType(string url)
{
return Path.GetExtension(url) switch
{
"ogg" => AudioType.OGGVORBIS,
"mp2" => AudioType.MPEG,
"mp3" => AudioType.MPEG,
"mod" => AudioType.MOD,
"wav" => AudioType.WAV,
"aif" => AudioType.IT,
_ => AudioType.UNKNOWN
};
}
public AudioType GetAudioType()
{
return GetAudioType(this.url);
}
#region URL Types #region URL Types
public bool IsText => ExtensionIs("txt", "html", "htm", "css", "js", "xml", "csv"); public bool IsText => ExtensionIs("txt", "html", "htm", "css", "js", "xml", "csv");
public bool IsJson => ExtensionIs(JsonURLTypes); public bool IsJson => ExtensionIs("json");
public bool IsImage => ExtensionIs(ImageURLTypes); public bool IsImage => ExtensionIs("jpg", "jpeg", "png", "gif", "bmp", "svg");
public bool IsAudio => ExtensionIs(AudioURLTypes); public bool IsDocument => ExtensionIs("pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx");
public bool IsVideo => ExtensionIs(VideoURLTypes);
public bool IsDocument => ExtensionIs(DocumentURLTypes);
#endregion #endregion
#region Operators #region Operators
[return: ReturnNotNull, ReturnNotSelf]
public static ToolURL operator |([In] ToolURL left, [In] string rightPath) public static ToolURL operator |(ToolURL left, string rightPath)
{ {
string baseUrl = left.GetFullURL(); string baseUrl = left.GetFullURL();
if (baseUrl.EndsWith("/")) if (baseUrl.EndsWith('/'))
{ {
return new ToolURL(baseUrl + rightPath); return new ToolURL(baseUrl + rightPath);
} }
@@ -645,90 +311,45 @@ namespace Convention
} }
} }
public ToolURL Open([In] string url) public ToolURL Open(string url)
{ {
this.url = url; this.url = url;
return this; return this;
} }
public ToolURL Close() public async Task<ToolURL> DownloadAsync(string localPath = null)
{
if (WebRequest != null)
{
WebRequest.Dispose();
WebRequest = null;
}
return this;
}
public ToolURL Download([In][Opt] string localPath = null)
{ {
if (!IsValid) if (!IsValid)
return this; return this;
if (localPath == null) if (localPath == null)
{ {
localPath = Path.Combine(Application.temporaryCachePath, GetFilename()); localPath = Path.Combine(Path.GetTempPath(), GetFilename());
} }
WebRequest = UnityWebRequest.Get(this.url); try
WebRequest.SendWebRequest();
while (!WebRequest.isDone)
{ {
// 等待请求完成 var response = await httpClient.GetAsync(this.url);
if (response.IsSuccessStatusCode)
{
var bytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync(localPath, bytes);
} }
}
if (WebRequest.result == UnityWebRequest.Result.Success) catch
{ {
File.WriteAllBytes(localPath, WebRequest.downloadHandler.data); // 下载失败
} }
return this; return this;
} }
public IEnumerator DownloadAsync([In] Action<bool> callback, [In][Opt] string localPath = null) public ToolURL Download(string localPath = null)
{ {
if (!IsValid) return DownloadAsync(localPath).GetAwaiter().GetResult();
{
callback(false);
yield break;
} }
if (localPath == null)
{
localPath = Path.Combine(Application.temporaryCachePath, GetFilename());
}
WebRequest = UnityWebRequest.Get(this.url);
yield return WebRequest.SendWebRequest();
if (WebRequest.result == UnityWebRequest.Result.Success)
{
File.WriteAllBytes(localPath, WebRequest.downloadHandler.data);
callback(true);
}
else
{
callback(false);
}
}
#endregion #endregion
}
#if UNITY_EDITOR
[SerializeField, ToolURL.URL] private string m_URL;
public void OnBeforeSerialize()
{
m_URL = this.FullURL;
} }
public void OnAfterDeserialize()
{
if (m_URL != this.FullURL)
{
this.url = m_URL;
}
}
#endif
}
}