using System.Net;
using XFEToolBox.Core.Chat;
using XFEToolBox.Server.Core.Chat;
using XFEExtension.NetCore.ServerInteractive.Attributes;
namespace XFEToolBox.Server.Services.Chat;
public partial class ChatAttachmentService : ChatServiceBase
{
[EntryPoint("v1/chat/attachments/init")]
public async Task InitializeAttachmentEntryPoint()
{
await ExecuteChatAsync(async repository =>
{
var fileName = GetString("fileName") ?? throw InvalidRequest("缺少 fileName。");
var totalBytes = GetInt64("totalBytes") ?? throw InvalidRequest("totalBytes 必须是整数。");
var attachment = await repository.InitializeAttachmentAsync(
User.Id,
fileName,
GetString("contentType"),
totalBytes,
GetString("sha256"));
return ToAttachmentInfo(attachment);
}, HttpStatusCode.Created);
}
[NoLog]
[EntryPoint("v1/chat/attachments/chunk")]
public async Task UploadAttachmentChunkEntryPoint()
{
await ExecuteChatAsync(async repository =>
{
var attachmentId = GetString("attachmentId") ?? throw InvalidRequest("缺少 attachmentId。");
var offset = GetInt64("offset") ?? throw InvalidRequest("offset 必须是整数。");
var chunkBase64 = GetString("chunkBase64", trim: false)
?? throw InvalidRequest("缺少 chunkBase64。");
if (chunkBase64.Length > checked((long)repository.MaxAttachmentChunkBytes * 2))
throw new ChatRepositoryException(ChatRepositoryError.PayloadTooLarge, "附件分块超过服务器限制。");
byte[] chunk;
try { chunk = Convert.FromBase64String(chunkBase64); }
catch (FormatException) { throw InvalidRequest("chunkBase64 不是有效的 Base64。"); }
var attachment = await repository.AppendAttachmentChunkAsync(attachmentId, User.Id, offset, chunk);
return ToAttachmentInfo(attachment);
});
}
[EntryPoint("v1/chat/attachments/complete")]
public async Task CompleteAttachmentEntryPoint()
{
await ExecuteChatAsync(async repository =>
{
var attachmentId = GetString("attachmentId") ?? throw InvalidRequest("缺少 attachmentId。");
var attachment = await repository.CompleteAttachmentAsync(
attachmentId,
User.Id,
GetString("sha256"));
return ToAttachmentInfo(attachment);
});
}
[NoLog]
[EntryPoint("v1/chat/attachments/download-chunk")]
public async Task DownloadAttachmentChunkEntryPoint()
{
await ExecuteChatAsync(async repository =>
{
var attachmentId = GetString("attachmentId") ?? throw InvalidRequest("缺少 attachmentId。");
var offset = GetInt64("offset") ?? 0;
var length = GetInt32("length") ?? repository.MaxAttachmentChunkBytes;
var chunk = await repository.DownloadAttachmentChunkAsync(
attachmentId, User.Id, offset, length);
return new ChatAttachmentChunkInfo
{
AttachmentId = chunk.AttachmentId,
Offset = chunk.Offset,
TotalBytes = chunk.TotalBytes,
DataBase64 = Convert.ToBase64String(chunk.Data),
EndOfFile = chunk.EndOfFile
};
});
}
}
using System.Net;
using XFEToolBox.Core.Chat;
using XFEToolBox.Server.Core.Chat;
using XFEExtension.NetCore.ServerInteractive.Attributes;
namespace XFEToolBox.Server.Services.Chat;
public partial class ChatAttachmentService : ChatServiceBase
{
[EntryPoint("v1/chat/attachments/init")]
public async Task InitializeAttachmentEntryPoint()
{
await ExecuteChatAsync(async repository =>
{
var fileName = GetString("fileName") ?? throw InvalidRequest("缺少 fileName。");
var totalBytes = GetInt64("totalBytes") ?? throw InvalidRequest("totalBytes 必须是整数。");
var attachment = await repository.InitializeAttachmentAsync(
User.Id,
fileName,
GetString("contentType"),
totalBytes,
GetString("sha256"));
return ToAttachmentInfo(attachment);
}, HttpStatusCode.Created);
}
[NoLog]
[EntryPoint("v1/chat/attachments/chunk")]
public async Task UploadAttachmentChunkEntryPoint()
{
await ExecuteChatAsync(async repository =>
{
var attachmentId = GetString("attachmentId") ?? throw InvalidRequest("缺少 attachmentId。");
var offset = GetInt64("offset") ?? throw InvalidRequest("offset 必须是整数。");
var chunkBase64 = GetString("chunkBase64", trim: false)
?? throw InvalidRequest("缺少 chunkBase64。");
if (chunkBase64.Length > checked((long)repository.MaxAttachmentChunkBytes * 2))
throw new ChatRepositoryException(ChatRepositoryError.PayloadTooLarge, "附件分块超过服务器限制。");
byte[] chunk;
try { chunk = Convert.FromBase64String(chunkBase64); }
catch (FormatException) { throw InvalidRequest("chunkBase64 不是有效的 Base64。"); }
var attachment = await repository.AppendAttachmentChunkAsync(attachmentId, User.Id, offset, chunk);
return ToAttachmentInfo(attachment);
});
}
[EntryPoint("v1/chat/attachments/complete")]
public async Task CompleteAttachmentEntryPoint()
{
await ExecuteChatAsync(async repository =>
{
var attachmentId = GetString("attachmentId") ?? throw InvalidRequest("缺少 attachmentId。");
var attachment = await repository.CompleteAttachmentAsync(
attachmentId,
User.Id,
GetString("sha256"));
return ToAttachmentInfo(attachment);
});
}
[NoLog]
[EntryPoint("v1/chat/attachments/download-chunk")]
public async Task DownloadAttachmentChunkEntryPoint()
{
await ExecuteChatAsync(async repository =>
{
var attachmentId = GetString("attachmentId") ?? throw InvalidRequest("缺少 attachmentId。");
var offset = GetInt64("offset") ?? 0;
var length = GetInt32("length") ?? repository.MaxAttachmentChunkBytes;
var chunk = await repository.DownloadAttachmentChunkAsync(
attachmentId, User.Id, offset, length);
return new ChatAttachmentChunkInfo
{
AttachmentId = chunk.AttachmentId,
Offset = chunk.Offset,
TotalBytes = chunk.TotalBytes,
DataBase64 = Convert.ToBase64String(chunk.Data),
EndOfFile = chunk.EndOfFile
};
});
}
}