Merge branch 'master' of https://gitea.nxsir.cn/nanxun/IM_NEW
This commit is contained in:
@@ -35,5 +35,12 @@ namespace FileService.Infrastructure.Reposites
|
||||
{
|
||||
return await db.Files.FirstOrDefaultAsync(x => x.Id == id);
|
||||
}
|
||||
public async Task<UploadFile?> FindByCheckSumGlobalAsync(string algorithm, string value)
|
||||
{
|
||||
return await db.Files.FirstOrDefaultAsync(
|
||||
x => x.CheckSum.Algorithm == algorithm &&
|
||||
x.CheckSum.Value == value
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,60 @@ namespace FileService.Infrastructure.Storage
|
||||
|
||||
public string ProviderCode => "Local";
|
||||
|
||||
/// <summary>
|
||||
/// 单次直传:直接写入 LocalRootPath/{bucket}/{objectKey}。
|
||||
/// bucket 传公开桶名即落到公开目录,可被静态托管直链访问。
|
||||
/// </summary>
|
||||
public async Task<StorageLocation> PutObjectAsync(PutObjectCommand command, CancellationToken token)
|
||||
{
|
||||
var fullPath = Path.Combine(providerOptions.LocalRootPath!, command.Bucket, command.ObjectKey);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(fullPath)!);
|
||||
|
||||
await using (var fs = new FileStream(fullPath, FileMode.Create))
|
||||
{
|
||||
await command.Content.CopyToAsync(fs, token);
|
||||
await fs.FlushAsync(token);
|
||||
}
|
||||
|
||||
return new StorageLocation(
|
||||
storageProvider: ProviderCode,
|
||||
bucket: command.Bucket,
|
||||
objectKey: command.ObjectKey,
|
||||
region: providerOptions.Region);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 公开桶文件返回静态托管直链;私有文件返回 null。
|
||||
/// </summary>
|
||||
public string? GetPublicUrl(StorageLocation location)
|
||||
{
|
||||
if (string.IsNullOrEmpty(providerOptions.PublicBucket) ||
|
||||
!string.Equals(location.Bucket, providerOptions.PublicBucket, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var baseUrl = (providerOptions.PublicBaseUrl ?? providerOptions.LocalUploadApiBaseUrl ?? string.Empty)
|
||||
.TrimEnd('/');
|
||||
var key = location.ObjectKey.Replace('\\', '/').TrimStart('/');
|
||||
return $"{baseUrl}/static/{key}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 打开本地文件读取流:LocalRootPath/{bucket}/{objectKey}。
|
||||
/// </summary>
|
||||
public Task<Stream> OpenReadAsync(StorageLocation location, CancellationToken token)
|
||||
{
|
||||
var fullPath = Path.Combine(providerOptions.LocalRootPath!, location.Bucket, location.ObjectKey);
|
||||
if (!File.Exists(fullPath))
|
||||
{
|
||||
throw new FileNotFoundException(fullPath);
|
||||
}
|
||||
|
||||
Stream stream = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
return Task.FromResult(stream);
|
||||
}
|
||||
|
||||
public async Task<CompleteUploadResult> CompleteUploadAsync(CompleteUploadCommand command, CancellationToken token)
|
||||
{
|
||||
var res = await MergeAsync(command.UploadSessionId, command.ObjectKey, command.Parts);
|
||||
|
||||
@@ -20,18 +20,40 @@ namespace FileService.Infrastructure.Storage
|
||||
public async Task SetAsync(UploadRuntimeCache upload)
|
||||
{
|
||||
string key = RedisHelper.GetUploadInfoKey(upload.UploadSessionId);
|
||||
await redis.SetAsync<UploadRuntimeCache>(key, upload);
|
||||
// 过期时间取 UploadRuntimeCache 的 ExpireAt 字段,兜底默认 24 小时
|
||||
var ttl = upload.ExpireAt > upload.CreatedAt
|
||||
? upload.ExpireAt - upload.CreatedAt
|
||||
: TimeSpan.FromHours(24);
|
||||
await redis.SetAsync<UploadRuntimeCache>(key, upload, ttl);
|
||||
|
||||
// 维护 taskId → sessionId 映射,用于 DeleteByTaskId 快速定位
|
||||
var mapKey = RedisHelper.GetUploadTaskSessionMapKey(upload.TaskId);
|
||||
await redis.SetAsync(mapKey, upload.UploadSessionId, ttl);
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(string sessionId)
|
||||
{
|
||||
string key = RedisHelper.GetUploadInfoKey(sessionId);
|
||||
|
||||
// 先取出缓存以清理映射 key
|
||||
var cache = await redis.GetAsync<UploadRuntimeCache>(key);
|
||||
if (cache != null)
|
||||
{
|
||||
var mapKey = RedisHelper.GetUploadTaskSessionMapKey(cache.TaskId);
|
||||
await redis.RemoveAsync(mapKey);
|
||||
}
|
||||
|
||||
await redis.RemoveAsync(key);
|
||||
}
|
||||
|
||||
public Task DeleteByTaskIdAsync(string taskId)
|
||||
public async Task DeleteByTaskIdAsync(string taskId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var mapKey = RedisHelper.GetUploadTaskSessionMapKey(taskId);
|
||||
var sessionId = await redis.GetAsync<string>(mapKey);
|
||||
if (sessionId != null)
|
||||
{
|
||||
await DeleteAsync(sessionId);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<UploadRuntimeCache?> GetAsync(string sessionId)
|
||||
|
||||
Reference in New Issue
Block a user