/// <summary> /// Copies one file in one or more chunks, if need be. /// Currently a chunk can be up to 4MB in size. /// </summary> /// <remarks> /// Before the file is copied, a check is performed if sending the file /// is necessary. If the file already exists on the target system (and the content /// is identical), then nothing more is done. /// </remarks> /// <param name="sourceFilePath"></param> /// <param name="destinationFilePath"></param> /// <param name="expectedFileSize"></param> private void CopyFileChunked(string sourceFilePath, string destinationFilePath, long expectedFileSize, bool forceCopy) { var thisHash = HashCodeCalculator.MD5(sourceFilePath); if (!forceCopy && Exists(destinationFilePath, expectedFileSize, thisHash)) { Log.InfoFormat("Skipping copy of '{0}' to '{1}' because the target file is already present", sourceFilePath, destinationFilePath); return; } Log.InfoFormat("Copying '{0}' to '{1}'...", sourceFilePath, destinationFilePath); using (var sourceStream = File.OpenRead(sourceFilePath)) { var fileSize = sourceStream.Length; var tasks = new TaskList(maxPending: MaxParallelCopyTasks); tasks.Add(_files.OpenFileAsync(destinationFilePath, fileSize)); var buffer = new byte[FilePacketBufferSize]; while (true) { var position = sourceStream.Position; var bytesRead = sourceStream.Read(buffer, 0, buffer.Length); if (bytesRead <= 0) { break; } tasks.Add(WriteAsync(bytesRead, position, buffer, destinationFilePath)); } tasks.Add(_files.CloseFileAsync(destinationFilePath)); tasks.WaitAll(); var clientHash = _files.CalculateMD5(destinationFilePath); if (!HashCodeCalculator.AreEqual(thisHash, clientHash)) { throw new NotImplementedException($"There has been an error while copying '{sourceFilePath}' to '{destinationFilePath}', the resulting hashes should be identical, but are not!"); } } }
public bool Exists(string filePath, long expectedFileSize, byte[] expectedHash) { filePath = NormalizeAndEvaluate(filePath); var info = _filesystem.GetFileInfo(filePath); if (!info.Exists) { Log.DebugFormat("The file '{0}' does not exist", filePath); return(false); } if (info.Length != expectedFileSize) { Log.DebugFormat("The file '{0}' exists, but has a different '{1}' filesize than the expected '{2}'", filePath, info.Length, expectedFileSize); return(false); } var hash = HashCodeCalculator.MD5(filePath); if (!HashCodeCalculator.AreEqual(hash, expectedHash)) { Log.DebugFormat( "The file '{0}' exists, has the expected size '{1}', but it's hash '{2}' differs from the expected one '{3}'", filePath, info.Length, HashCodeCalculator.ToString(hash), HashCodeCalculator.ToString(expectedHash)); return(false); } Log.DebugFormat( "The file '{0}' exists, has the expected size '{1}' and hash '{2}'", filePath, info.Length, HashCodeCalculator.ToString(hash)); return(true); }