feat: 优化AI图片存储与访问流程

- 统一图片存储服务地址常量,返回完整可访问URL
- 图片上传接口支持匿名访问,并按日期创建存储目录
- ImageStoreTask 移除无用生成图片 Base64 字段,调整大字段存储配置
- 创建图片任务时补充 ModelId 信息
- 优先使用 Authorization 头部,避免覆盖已有认证信息
- 前端补充 Element Plus Descriptions 组件类型声明
This commit is contained in:
ccnetcore
2026-01-02 21:32:48 +08:00
parent 436b5b910c
commit ba95d1798f
5 changed files with 29 additions and 22 deletions

View File

@@ -98,7 +98,8 @@ public class AiImageService : ApplicationService
ReferenceImagesUrl = new List<string>(),
TaskStatus = TaskStatusEnum.Processing,
UserId = userId,
TokenId = input.TokenId
TokenId = input.TokenId,
ModelId = input.ModelId
};
await _imageTaskRepository.InsertAsync(task);
@@ -146,6 +147,7 @@ public class AiImageService : ApplicationService
/// <param name="base64Data">Base64图片数据包含前缀如 data:image/png;base64,</param>
/// <returns>图片访问URL</returns>
[HttpPost("ai-image/upload-base64")]
[AllowAnonymous]
public async Task<string> UploadBase64ToUrlAsync([FromBody] string base64Data)
{
if (string.IsNullOrWhiteSpace(base64Data))
@@ -194,22 +196,31 @@ public class AiImageService : ApplicationService
throw new UserFriendlyException("Base64格式无效");
}
// 创建存储目录
var uploadPath = Path.Combine(_webHostEnvironment.ContentRootPath, "wwwroot", "ai-images");
// ==============================
// ✅ 按日期创建目录yyyyMMdd
// ==============================
var dateFolder = DateTime.Now.ToString("yyyyMMdd");
var uploadPath = Path.Combine(
_webHostEnvironment.ContentRootPath,
"wwwroot",
"ai-images",
dateFolder
);
if (!Directory.Exists(uploadPath))
{
Directory.CreateDirectory(uploadPath);
}
// 生成文件名并保存
// 保存文件
var fileId = _guidGenerator.Create();
var fileName = $"{fileId}{extension}";
var filePath = Path.Combine(uploadPath, fileName);
await File.WriteAllBytesAsync(filePath, imageBytes);
// 返回访问URL
return $"/ai-images/{fileName}";
// 返回包含日期目录的访问URL
return $"/wwwroot/ai-images/{dateFolder}/{fileName}";
}
/// <summary>

View File

@@ -16,20 +16,15 @@ public class ImageStoreTaskAggregateRoot : FullAuditedAggregateRoot<Guid>
/// <summary>
/// 参考图PrefixBase64带前缀如 data:image/png;base64,xxx
/// </summary>
[SugarColumn(IsJson = true)]
[SugarColumn(IsJson = true,ColumnDataType = StaticConfig.CodeFirst_BigString)]
public List<string> ReferenceImagesPrefixBase64 { get; set; }
/// <summary>
/// 参考图url
/// </summary>
[SugarColumn(IsJson = true)]
public List<string> ReferenceImagesUrl { get; set; }
/// <summary>
/// 生成图片PrefixBase64带前缀如 data:image/png;base64,xxx
/// </summary>
public string? StorePrefixBase64 { get; set; }
/// <summary>
/// 图片绝对路径

View File

@@ -976,7 +976,7 @@ public class AiGateWayManager : DomainService
}
}
private const string ImageStoreHost = "http://localhost:19001/api/app";
/// <summary>
/// Gemini 生成(Image)-非流式-缓存处理
/// 返回图片绝对路径
@@ -1010,12 +1010,11 @@ public class AiGateWayManager : DomainService
//远程调用上传接口将base64转换为URL
var httpClient = LazyServiceProvider.LazyGetRequiredService<IHttpClientFactory>().CreateClient();
// var uploadUrl = $"https://ccnetcore.com/prod-api/ai-hub/ai-image/upload-base64";
var uploadUrl = $"http://localhost:19001/api/app/ai-image/upload-base64";
var uploadUrl = $"{ImageStoreHost}/ai-image/upload-base64";
var content = new StringContent(JsonSerializer.Serialize(imageBase64), Encoding.UTF8, "application/json");
var uploadResponse = await httpClient.PostAsync(uploadUrl, content, cancellationToken);
uploadResponse.EnsureSuccessStatusCode();
var storeUrl = await uploadResponse.Content.ReadAsStringAsync(cancellationToken);
storeUrl = storeUrl.Trim('"'); // 移除JSON字符串的引号
var tokenUsage = new ThorUsageResponse
{
@@ -1042,8 +1041,7 @@ public class AiGateWayManager : DomainService
}
//设置存储base64和url
imageStoreTask.StorePrefixBase64 = imageBase64;
imageStoreTask.SetSuccess(storeUrl);
imageStoreTask.SetSuccess($"{ImageStoreHost}{storeUrl}");
await _imageStoreTaskRepository.UpdateAsync(imageStoreTask);
}