更新
This commit is contained in:
2026-02-23 18:52:32 +08:00
parent d429560511
commit 123fa6a7aa
81 changed files with 5952 additions and 407 deletions
+6
View File
@@ -105,5 +105,11 @@
// 3.9 会话相关错误(3100 ~ 3199
/// <summary>发送时异常</summary>
public static CodeDefine CONVERSATION_NOT_FOUND = new CodeDefine(3100, "会话不存在");
// 3.9 文件相关错误(3200 ~ 3299
/// <summary>分片不存在异常</summary>
public static CodeDefine CHUNKE_NOT_FOUND = new CodeDefine(3201, "分片不存在");
/// <summary>分片合并异常</summary>
public static CodeDefine CHUNKE_COMBINE_FAIL = new CodeDefine(3202, "分片合并失败");
}
}
@@ -0,0 +1,51 @@
namespace IM_API.Tools
{
public static class ObjectNameGenerator
{
public static string Generate(ObjectNameContext ctx)
{
var ext = GetExtension(ctx.FileName, ctx.ContentType);
var shortId = Guid.NewGuid().ToString("N")[..12];
var parts = new List<string>
{
ctx.Biz,
ctx.Now.Year.ToString(),
ctx.Now.Month.ToString("D2")
};
if (ctx.UserId.HasValue)
{
parts.Add(ctx.UserId.Value.ToString());
}
parts.Add($"{shortId}{ext}");
return string.Join("/", parts);
}
private static string GetExtension(string fileName, string contentType)
{
var ext = Path.GetExtension(fileName);
if (!string.IsNullOrWhiteSpace(ext))
return ext.ToLowerInvariant();
return contentType switch
{
"image/jpeg" => ".jpg",
"image/png" => ".png",
"video/mp4" => ".mp4",
_ => ".bin"
};
}
}
public class ObjectNameContext
{
public string Biz { get; init; } = "IM";
public long? UserId { get; init; }
public string FileName { get; init; } = default!;
public string ContentType { get; init; } = default!;
public DateTimeOffset Now { get; init; } = DateTimeOffset.UtcNow;
}
}
+8 -5
View File
@@ -2,10 +2,13 @@
{
public static class RedisKeys
{
public static string GetUserinfoKey(string userId) => $"user::uinfo::{userId}";
public static string GetUserinfoKeyByUsername(string username) => $"user::uinfobyid::{username}";
public static string GetSequenceIdKey(string streamKey) => $"chat::seq::{streamKey}";
public static string GetSequenceIdLockKey(string streamKey) => $"lock::seq::{streamKey}";
public static string GetConnectionIdKey(string userId) => $"signalr::user::con::{userId}";
public static string GetUserinfoKey(string userId) => $"user:uinfo:{userId}";
public static string GetUserinfoKeyByUsername(string username) => $"user:uinfobyid:{username}";
public static string GetSequenceIdKey(string streamKey) => $"chat:seq:{streamKey}";
public static string GetSequenceIdLockKey(string streamKey) => $"lock:seq:{streamKey}";
public static string GetConnectionIdKey(string userId) => $"signalr:user:con:{userId}";
public static string GetUploadPartKey(Guid taskId) => $"upload:task:{taskId}:parts";
public static string MergeStatus(Guid taskId) => $"upload:task:{taskId}:merge";
}
}
+64
View File
@@ -0,0 +1,64 @@
using SixLabors.ImageSharp;
using System.Text.Json;
using System.Text.Json.Nodes;
namespace IM_API.Tools
{
public static class UrlTools
{
public static string GetFullUrl(string objectName, string provider, string? baseUrl)
{
return provider switch
{
"Local" => $"{baseUrl}/uploads/files/{objectName}",
_ => "http://baidu.com",
};
}
public static async Task<(int width, int height)> GetImageWH(string url)
{
using var httpClient = new HttpClient();
var stream = await httpClient.GetStreamAsync(url);
var info = await Image.IdentifyAsync(stream);
return (info.Width, info.Height);
}
public static string ProcessMessageUrl(string contentJson, string? localBaseUrl)
{
// 1. 解析 JSON 文档(比反序列化快得多)
using var doc = JsonDocument.Parse(contentJson);
var root = doc.RootElement;
// 2. 获取 Provider 字段
string provider = root.GetProperty("provider").GetString();
// 3. 根据 Provider 决定前缀
string prefix = GetFullUrl("", provider, localBaseUrl);
// 4. 重新组装(如果只是为了给前端看,建议直接返回带前缀的对象或字符串)
// 这里推荐用 JsonNode 方便修改并返回字符串
var node = JsonNode.Parse(contentJson);
node["url"] = $"{prefix}{node["url"]}";
node["thumb"] = $"{prefix}{node["thumb"]}";
return node.ToJsonString();
}
public static Stream Base64ToStream(string base64String)
{
if (string.IsNullOrEmpty(base64String))
throw new ArgumentNullException(nameof(base64String));
// 1. 自动处理可能存在的 Base64 Data URL 前缀
string base64Data = base64String.Contains(",")
? base64String.Split(',')[1]
: base64String;
// 2. 解码为字节数组
byte[] bytes = Convert.FromBase64String(base64Data);
// 3. 包装进 MemoryStream
// 注意:这里直接把 Position 设为 0,符合“方法a”产生即用的原则
return new MemoryStream(bytes);
}
}
}