///<summary>Downloads the file from the server.</summary> ///<param name="basePath">The directory to download into.</param> ///<param name="ui">An optional IProgressReporter to report progress.</param> ///<exception cref="InvalidDataException">The hash didn't match.</exception> public void DownloadFile(string basePath, IProgressReporter ui) { if (!Directory.Exists(basePath)) { throw new DirectoryNotFoundException(basePath + " does not exist"); } var filePath = Path.Combine(basePath, RelativePath); if (File.Exists(filePath)) { throw new InvalidOperationException(filePath + " already exists"); } Directory.CreateDirectory(Path.GetDirectoryName(filePath)); //Won't throw ui = ui ?? new EmptyProgressReporter(); long actualSize; var request = WebRequest.Create(new Uri(UpdateConfig.Standard.BaseUri, RemoteUrl)); using (var hasher = hasherCreator()) { using (var transform = UpdateChecker.CreateFileDecryptor()) using (var response = request.GetResponse()) using (var cypherStream = response.GetResponseStream()) using (var decryptingStream = new CryptoStream(cypherStream, transform, CryptoStreamMode.Read)) using (var unzipper = new GZipStream(decryptingStream, CompressionMode.Decompress)) using (var hashingStream = new CryptoStream(unzipper, hasher, CryptoStreamMode.Read)) using (var fileStream = File.Create(filePath)) { actualSize = hashingStream.CopyTo(fileStream, Length, ui); } if (Length != actualSize) { File.Delete(filePath); throw new InvalidDataException("Bad length"); } if (!hasher.Hash.SequenceEqual(hash)) { File.Delete(filePath); throw new InvalidDataException("Bad hash"); } File.SetLastWriteTimeUtc(filePath, DateModifiedUtc); } }