101 lines
3.6 KiB
C#
101 lines
3.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Chtn.CSharp.SDK.Core;
|
|
using Chtn.CSharp.SDK.Models.Media;
|
|
using Chtn.CSharp.SDK.Models;
|
|
|
|
namespace Chtn.CSharp.SDK.Services
|
|
{
|
|
public interface IFileUploadService
|
|
{
|
|
Task<string> UploadFiles(string tempMsgId, string roomId, string userId, List<FileData> files, IFileUploadProgressListener listener);
|
|
}
|
|
|
|
public class FileUploadService : IFileUploadService
|
|
{
|
|
private readonly ApiClient _apiClient;
|
|
private readonly ApiClient _cdnClient;
|
|
private const int MIN_CHUNK_SIZE = 25000000;
|
|
|
|
public FileUploadService(ApiClient apiClient, ApiClient cdnClient)
|
|
{
|
|
_apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
|
|
_cdnClient = cdnClient ?? throw new ArgumentNullException(nameof(cdnClient));
|
|
}
|
|
|
|
private int CalculateChunkSize(long totalSize)
|
|
{
|
|
long chunks = totalSize / MIN_CHUNK_SIZE;
|
|
if (chunks == 0) return (int)totalSize;
|
|
long chunkSize = (long)Math.Ceiling((double)totalSize / chunks);
|
|
return (int)Math.Max(chunkSize, MIN_CHUNK_SIZE);
|
|
}
|
|
|
|
public async Task<string> UploadFiles(string tempMsgId, string roomId, string userId, List<FileData> files, IFileUploadProgressListener listener)
|
|
{
|
|
var registrations = files.Select(f => new FileUploadRegistration
|
|
{
|
|
FileId = f.FileId,
|
|
Name = f.Name,
|
|
Type = f.Type,
|
|
Size = f.Data.Length
|
|
}).ToList();
|
|
|
|
var regReq = new RegisterUploadReq
|
|
{
|
|
RoomId = roomId,
|
|
UserId = userId,
|
|
Files = registrations
|
|
};
|
|
|
|
var resp = await _apiClient.PostAsync<RegisterUploadReq, RegisterUploadResp>("chat/cdnRegisterUpload", regReq);
|
|
string uploadId = resp.UploadId;
|
|
|
|
for (int i = 0; i < files.Count; i++)
|
|
{
|
|
await UploadFileInternal(tempMsgId, uploadId, roomId, userId, files[i], registrations[i], listener);
|
|
}
|
|
|
|
await FinishUploadInternal(roomId, userId, uploadId);
|
|
|
|
return uploadId;
|
|
}
|
|
|
|
private async Task UploadFileInternal(string tempMsgId, string uploadId, string roomId, string userId, FileData file, FileUploadRegistration registration, IFileUploadProgressListener listener)
|
|
{
|
|
int chunkSize = CalculateChunkSize(file.Data.Length);
|
|
int totalChunks = (int)Math.Ceiling((double)file.Data.Length / chunkSize);
|
|
|
|
for (int i = 0; i < totalChunks; i++)
|
|
{
|
|
int start = i * chunkSize;
|
|
int length = (int)Math.Min(chunkSize, file.Data.Length - start);
|
|
|
|
byte[] chunkData = new byte[length];
|
|
Array.Copy(file.Data, start, chunkData, 0, length);
|
|
|
|
var chunkReq = new ChunkUploadReq
|
|
{
|
|
UploadId = uploadId,
|
|
ChunkIndex = i,
|
|
Data = chunkData
|
|
};
|
|
|
|
await _cdnClient.PostAsync<ChunkUploadReq, object>("chat/uploadChunk", chunkReq);
|
|
listener?.FileProgressUpdate(tempMsgId, file.FileId, totalChunks, i);
|
|
}
|
|
}
|
|
|
|
private async Task FinishUploadInternal(string roomId, string userId, string uploadId)
|
|
{
|
|
var finishReq = new FinishUploadReq
|
|
{
|
|
UploadId = uploadId
|
|
};
|
|
|
|
await _cdnClient.PostAsync<FinishUploadReq, object>("chat/finishUpload", finishReq);
|
|
}
|
|
}
|
|
} |