136 lines
5.5 KiB
C#
136 lines
5.5 KiB
C#
using AutoMapper;
|
|
using FileService.Application.Ports;
|
|
using FileService.Application.StorageContracts;
|
|
using FileService.Domain.Entities;
|
|
using FileService.Domain.IReposities;
|
|
using IM.Commons;
|
|
using IM.Commons.IntegrationEvents;
|
|
using IM.InitCommon;
|
|
using MassTransit;
|
|
using MassTransit.Internals;
|
|
using Microsoft.Extensions.Options;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace FileService.Application.UploadFileTask
|
|
{
|
|
public class UploadFileTaskService(IUploadTaskReposity reposity,
|
|
IMapper mapper, IObjectStorageRouter router,
|
|
IOptions<StorageOptions> options, IStorageRedisCache redis,
|
|
IPublishEndpoint endpoint
|
|
)
|
|
{
|
|
private readonly IUploadTaskReposity reposity = reposity;
|
|
private readonly IMapper mapper = mapper;
|
|
private readonly IObjectStorageRouter router = router;
|
|
private readonly IOptions<StorageOptions> options = options;
|
|
private readonly IStorageRedisCache redis = redis;
|
|
private readonly IPublishEndpoint endpoint = endpoint;
|
|
private readonly IObjectStoragePort storage = router.Route(options.Value.DefaultProviderCode);
|
|
|
|
public async Task<Result<TaskInitResponse>> InitTaskAsync(UploadTaskInitCommand command)
|
|
{
|
|
CancellationToken cancellationToken = CancellationToken.None;
|
|
var task = command.ToUploadTask();
|
|
|
|
var storageOption = options.Value.Providers[options.Value.DefaultProviderCode];
|
|
var storage = router.Route(storageOption.ProviderCode);
|
|
var initRes = await storage.InitUploadAsync(new StorageContracts.InitiateUploadCommand(
|
|
ProviderCode: storageOption.ProviderCode,
|
|
Bucket: storageOption.Bucket,
|
|
ObjectKey: storageOption.Endpoint,
|
|
ContentType:task.ContentType.Value,
|
|
ContentLength: command.FileSize,
|
|
null
|
|
), cancellationToken);
|
|
|
|
var res = mapper.Map<TaskInitResponse>(initRes);
|
|
res.TaskId = task.Id;
|
|
|
|
task.StartUpload();
|
|
reposity.Create(task);
|
|
|
|
await redis.SetAsync(new StorageContracts.UploadRuntimeCache(
|
|
taskId: task.Id.ToString(),
|
|
providerCode: storage.ProviderCode,
|
|
uploadSessionId: res.UploadSessionId,
|
|
bucket: storageOption.Bucket,
|
|
region: storageOption.Region,
|
|
objectKey: storageOption.Endpoint,
|
|
fileSize: task.FileSize,
|
|
totalPartCount: (int)(task.FileSize % storageOption.DefaultPartSizeBytes > 0 ?
|
|
(task.FileSize / storageOption.DefaultPartSizeBytes) + 1 :
|
|
task.FileSize / storageOption.DefaultPartSizeBytes)
|
|
));
|
|
|
|
return Result.Success(res);
|
|
|
|
}
|
|
|
|
public async Task<Result<PresignedUrl>> GenerateUrlAsync(string sessionId, int partNum, Guid userId, CancellationToken token = default)
|
|
{
|
|
var taskCache = await redis.GetAsync(sessionId);
|
|
if(taskCache is null)
|
|
{
|
|
return Result.Fail<PresignedUrl>(ResultCode.CHUNK_NOT_FOUND);
|
|
}
|
|
|
|
var presignUrl = await storage.GenerateUploadUrlAsync(new GenerateUploadUrlCommand(
|
|
ProviderCode: taskCache.ProviderCode,
|
|
Bucket: taskCache.Bucket,
|
|
ObjectKey: taskCache.ObjectKey,
|
|
UploadSessionId: taskCache.UploadSessionId,
|
|
PartNumber: partNum,
|
|
ExpiresIn: options.Value.Providers[options.Value.DefaultProviderCode].UploadUrlExpiresIn
|
|
), token);
|
|
|
|
return Result.Success(presignUrl);
|
|
}
|
|
|
|
public async Task<Result<UploadTaskResponse>> CompleteTaskAsync(UploadTaskCompleteCommand command, CancellationToken cancellationToken = default)
|
|
{
|
|
var taskCache = await redis.GetAsync(command.UploadSessionId);
|
|
|
|
if(taskCache is null)
|
|
{
|
|
return Result.Fail<UploadTaskResponse>(ResultCode.CHUNK_NOT_FOUND);
|
|
}
|
|
|
|
var task = await reposity.FindByIdAsync(Guid.Parse(taskCache.TaskId));
|
|
//var res = await storage.CompleteUploadAsync(new CompleteUploadCommand(
|
|
// ProviderCode: taskCache.ProviderCode,
|
|
// Bucket: taskCache.Bucket,
|
|
// Region: taskCache.Region,
|
|
// ObjectKey: taskCache.ObjectKey,
|
|
// UploadSessionId: taskCache.UploadSessionId,
|
|
// Parts: command.Parts
|
|
// ), cancellationToken);
|
|
|
|
task.CompleteUpload(new Domain.ValueObjects.StorageLocation(
|
|
taskCache.ProviderCode, taskCache.Bucket,
|
|
taskCache.ObjectKey, taskCache.Region
|
|
));
|
|
|
|
await endpoint.Publish(new UploadTaskCompleteEvent()
|
|
{
|
|
Bucket = taskCache.Bucket,
|
|
FileName = task.FileName.ToString(),
|
|
ObjectKey = taskCache.ObjectKey,
|
|
Parts = command.Parts.Select(s =>
|
|
new IM.Commons.IntegrationEvents.UploadPart(
|
|
s.PartNumber, s.ETag, s.Size, s.Checksum)
|
|
).ToList(),
|
|
ProviderCode = taskCache.ProviderCode,
|
|
Region = taskCache.Region,
|
|
SessionId = command.UploadSessionId,
|
|
TaskId = task.Id
|
|
});
|
|
|
|
return Result.Success(mapper.Map<UploadTaskResponse>(task));
|
|
}
|
|
}
|
|
}
|