You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
72 lines
2.6 KiB
72 lines
2.6 KiB
1 year ago
|
using System.Buffers;
|
||
1 year ago
|
using StabilityMatrix.Core.Models.Progress;
|
||
1 year ago
|
|
||
1 year ago
|
namespace StabilityMatrix.Core.Helper;
|
||
1 year ago
|
|
||
|
public static class FileTransfers
|
||
|
{
|
||
1 year ago
|
/// <summary>
|
||
|
/// Determines suitable buffer size based on stream length.
|
||
|
/// </summary>
|
||
|
/// <param name="totalBytes"></param>
|
||
|
/// <returns></returns>
|
||
|
public static ulong GetBufferSize(ulong totalBytes) => totalBytes switch
|
||
|
{
|
||
|
< Size.MiB => 8 * Size.KiB,
|
||
|
< 100 * Size.MiB => 16 * Size.KiB,
|
||
|
< 500 * Size.MiB => Size.MiB,
|
||
|
< Size.GiB => 16 * Size.MiB,
|
||
|
_ => 32 * Size.MiB
|
||
|
};
|
||
|
|
||
1 year ago
|
public static async Task CopyFiles(Dictionary<string, string> files, IProgress<ProgressReport>? fileProgress = default, IProgress<ProgressReport>? totalProgress = default)
|
||
|
{
|
||
|
var totalFiles = files.Count;
|
||
|
var currentFiles = 0;
|
||
|
var totalSize = Convert.ToUInt64(files.Keys.Select(x => new FileInfo(x).Length).Sum());
|
||
|
var totalRead = 0ul;
|
||
|
|
||
|
foreach(var (sourcePath, destPath) in files)
|
||
|
{
|
||
|
var totalReadForFile = 0ul;
|
||
|
|
||
|
await using var outStream = new FileStream(destPath, FileMode.Create, FileAccess.Write, FileShare.Read);
|
||
|
await using var inStream = new FileStream(sourcePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||
|
var fileSize = (ulong) inStream.Length;
|
||
|
var fileName = Path.GetFileName(sourcePath);
|
||
1 year ago
|
currentFiles++;
|
||
1 year ago
|
await CopyStream(inStream , outStream, fileReadBytes =>
|
||
|
{
|
||
|
var lastRead = totalReadForFile;
|
||
|
totalReadForFile = Convert.ToUInt64(fileReadBytes);
|
||
|
totalRead += totalReadForFile - lastRead;
|
||
|
fileProgress?.Report(new ProgressReport(totalReadForFile, fileSize, fileName, $"{currentFiles}/{totalFiles}"));
|
||
|
totalProgress?.Report(new ProgressReport(totalRead, totalSize, fileName, $"{currentFiles}/{totalFiles}"));
|
||
|
} );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static async Task CopyStream(Stream from, Stream to, Action<long> progress)
|
||
|
{
|
||
1 year ago
|
var shared = ArrayPool<byte>.Shared;
|
||
1 year ago
|
var bufferSize = (int) GetBufferSize((ulong) from.Length);
|
||
|
var buffer = shared.Rent(bufferSize);
|
||
1 year ago
|
var totalRead = 0L;
|
||
1 year ago
|
|
||
|
try
|
||
|
{
|
||
|
while (totalRead < from.Length)
|
||
|
{
|
||
1 year ago
|
var read = await from.ReadAsync(buffer.AsMemory(0, bufferSize));
|
||
1 year ago
|
await to.WriteAsync(buffer.AsMemory(0, read));
|
||
|
totalRead += read;
|
||
|
progress(totalRead);
|
||
|
}
|
||
|
}
|
||
|
finally
|
||
1 year ago
|
{
|
||
1 year ago
|
shared.Return(buffer);
|
||
1 year ago
|
}
|
||
|
}
|
||
|
}
|