using System; using System.Collections.Generic; using System.IO; using ZeroLevel.Services.HashFunctions; namespace ZeroLevel.Network.FileTransfer { internal sealed class FileReader { private readonly FileStartFrame _startInfo; public string Path { get; } private const int CHUNK_SIZE = 512 * 1024; public FileReader(string path) { Path = path; _startInfo = FileStartFrame.GetTransferFileInfo(path); } public FileStartFrame GetStartInfo() { return _startInfo; } public IEnumerable Read() { long offset = 0; using (FileStream stream = new FileStream(Path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { int bytesRead; var buffer = new byte[CHUNK_SIZE]; while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0) { var fragment = new FileFrame { UploadFileTaskId = _startInfo.UploadFileTaskId, Offset = offset * CHUNK_SIZE, Payload = new byte[bytesRead] }; Array.Copy(buffer, 0, fragment.Payload, 0, bytesRead); var hash = Murmur3.ComputeHash(fragment.Payload); fragment.ChecksumL = BitConverter.ToUInt64(hash, 0); fragment.ChecksumH = BitConverter.ToUInt64(hash, 8); offset = offset + 1; yield return fragment; } } } public FileEndFrame GetCompleteInfo() { return new FileEndFrame { UploadFileTaskId = _startInfo.UploadFileTaskId }; } } }