public async Task DoesNotUploadWhenThereIsExistingFileWithSameHash() { // arrange var fileName = "foo.txt"; string filePath = Path.Combine(Path.GetTempPath(), fileName); File.WriteAllText(filePath, "123"); long fullFileSize = new FileInfo(filePath).Length; var hashForFile = new MD5FileHasher().CalculateHashForFile(filePath); int resourceId = 1; var checkFileResult = new CheckFileResult { StatusCode = HttpStatusCode.NoContent, LastModified = DateTimeOffset.UtcNow, FileNameOnServer = fileName, HashForFileOnServer = hashForFile }; // Have CheckFileAsync return NoContent with a hash mockFileService.Setup( service => service.CheckFileAsync(resourceId)) .ReturnsAsync(checkFileResult); // act await this.classUnderTest.UploadFileAsync(resourceId, filePath, this.cancellationToken); // assert mockFileService.Verify( service => service.CheckFileAsync(1), Times.Once); mockFileService.Verify( service => service.SetUploadedAsync(1), Times.Once); mockFileService.Verify( service => service.CreateNewUploadSessionAsync(resourceId), Times.Never); mockFileService.Verify( service => service.UploadStreamAsync(resourceId, It.IsAny <Guid>(), It.IsAny <Stream>(), It.IsAny <FilePart>(), fileName, fullFileSize, It.IsAny <int>()), Times.Never); mockFileService.Verify( service => service.CommitAsync(resourceId, It.IsAny <Guid>(), fileName, hashForFile, fullFileSize, It.IsAny <IList <FilePart> >()), Times.Never); }
/// <inheritdoc /> /// <summary> /// This calls GET Files({resourceId}) /// </summary> /// <param name="resourceId"></param> /// <param name="utTempPath"></param> /// <returns></returns> public async Task <CheckFileResult> DownloadFileAsync(int resourceId, string utTempPath) { if (resourceId <= 0) { throw new ArgumentOutOfRangeException(nameof(resourceId)); } var fullUri = new Uri(this.mdsBaseUrl, $"Files({resourceId})"); var method = Convert.ToString(HttpMethod.Get); await this.SetAuthorizationHeaderInHttpClientAsync(resourceId); OnNavigating(new NavigatingEventArgs(resourceId, method, fullUri)); var policy = GetRetryPolicy(resourceId, method, fullUri); var httpResponse = await policy .ExecuteAsync(() => { var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, fullUri); httpRequestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*")); return(_httpClient.SendAsync(httpRequestMessage, this.cancellationToken)); }); // we don't want to write the content in this case as the file can be very large OnNavigated( new NavigatedEventArgs(resourceId, method, fullUri, httpResponse.StatusCode.ToString(), string.Empty)); switch (httpResponse.StatusCode) { case HttpStatusCode.OK: { var headersLastModified = httpResponse.Content.Headers.LastModified; var headersContentMd5 = httpResponse.Content.Headers.ContentMD5; var contentDispositionFileName = httpResponse.Content.Headers.ContentDisposition?.FileName; var result = new CheckFileResult { StatusCode = httpResponse.StatusCode, LastModified = headersLastModified, FileNameOnServer = contentDispositionFileName, FullUri = fullUri }; if (headersContentMd5 != null) { result.HashForFileOnServer = Encoding.UTF8.GetString(headersContentMd5); } var contentStream = await httpResponse.Content.ReadAsStreamAsync(); if (contentDispositionFileName != null) { var fullPath = Path.Combine(utTempPath, contentDispositionFileName); using (FileStream destinationStream = new FileStream(fullPath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: DefaultBufferSize, useAsync: true)) { await contentStream.CopyToAsync(destinationStream); } } return(result); } case HttpStatusCode.NotFound: { // this is acceptable response if the file does not exist on the server return(new CheckFileResult { StatusCode = httpResponse.StatusCode, FullUri = fullUri }); } default: { var content = await httpResponse.Content.ReadAsStringAsync(); return(new CheckFileResult { StatusCode = httpResponse.StatusCode, Error = content, FullUri = fullUri }); } } }
/// <inheritdoc /> /// <summary> /// This calls HEAD Files({resourceId}) /// </summary> /// <param name="resourceId"></param> /// <returns></returns> public async Task <CheckFileResult> CheckFileAsync(int resourceId) { if (resourceId <= 0) { throw new ArgumentOutOfRangeException(nameof(resourceId)); } var fullUri = new Uri(mdsBaseUrl, $"Files({resourceId})"); var method = Convert.ToString(HttpMethod.Get); await this.SetAuthorizationHeaderInHttpClientAsync(resourceId); OnNavigating(new NavigatingEventArgs(resourceId, method, fullUri)); var policy = GetRetryPolicy(resourceId, method, fullUri); var httpResponse = await policy .ExecuteAsync(() => { var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, fullUri); return(_httpClient.SendAsync(httpRequestMessage, this.cancellationToken)); }); var content = await httpResponse.Content.ReadAsStringAsync(); OnNavigated( new NavigatedEventArgs(resourceId, method, fullUri, httpResponse.StatusCode.ToString(), content)); switch (httpResponse.StatusCode) { case HttpStatusCode.OK: { throw new InvalidOperationException($"The url, {fullUri}, sent back the whole file instead of just the headers. You may be running an old version of MDS. Please install the latest version of MDS from the Installer."); } case HttpStatusCode.NoContent: { // HEAD returns NoContent on success var headersLastModified = httpResponse.Content.Headers.LastModified; var headersContentMd5 = httpResponse.Content.Headers.ContentMD5; var contentDispositionFileName = httpResponse.Content.Headers.ContentDisposition?.FileName; if (!string.IsNullOrWhiteSpace(contentDispositionFileName)) { contentDispositionFileName = contentDispositionFileName.Replace("\\", string.Empty).Replace("\"", string.Empty); } var result = new CheckFileResult { StatusCode = httpResponse.StatusCode, LastModified = headersLastModified, FileNameOnServer = contentDispositionFileName, FullUri = fullUri }; if (headersContentMd5 != null) { result.HashForFileOnServer = Encoding.UTF8.GetString(headersContentMd5); } return(result); } case HttpStatusCode.NotFound: { // this is acceptable response if the file does not exist on the server return(new CheckFileResult { StatusCode = httpResponse.StatusCode, FullUri = fullUri }); } default: { return(new CheckFileResult { StatusCode = httpResponse.StatusCode, Error = content, FullUri = fullUri }); } } }
public async Task UploadFileIsSuccessful() { // arrange var fileName = "foo.txt"; string filePath = Path.Combine(Path.GetTempPath(), fileName); File.WriteAllText(filePath, "123"); long fullFileSize = new FileInfo(filePath).Length; var hashForFile = new MD5FileHasher().CalculateHashForFile(filePath); int resourceId = 1; var checkFileResult = new CheckFileResult { StatusCode = HttpStatusCode.NoContent, LastModified = DateTimeOffset.UtcNow, FileNameOnServer = fileName, HashForFileOnServer = "MyHash" }; mockFileService.Setup( service => service.CheckFileAsync(resourceId)) .ReturnsAsync(checkFileResult); var sessionId = Guid.NewGuid(); var uploadSession = new UploadSession { SessionId = sessionId, FileUploadChunkSizeInBytes = 1, FileUploadMaxFileSizeInMegabytes = 10 }; var createSessionResult = new CreateSessionResult { StatusCode = HttpStatusCode.OK, Session = uploadSession }; mockFileService.Setup( service => service.CreateNewUploadSessionAsync(resourceId)) .ReturnsAsync(createSessionResult); var fileSplitter = new FileSplitter(); var countOfFileParts = fileSplitter.GetCountOfFileParts(createSessionResult.Session.FileUploadChunkSizeInBytes, fullFileSize); var uploadStreamResult = new UploadStreamResult { StatusCode = HttpStatusCode.OK, PartsUploaded = 1 }; mockFileService.Setup( service => service.UploadStreamAsync(resourceId, sessionId, It.IsAny <Stream>(), It.IsAny <FilePart>(), fileName, fullFileSize, countOfFileParts)) .ReturnsAsync(uploadStreamResult); var commitResult = new CommitResult { StatusCode = HttpStatusCode.OK, Session = uploadSession }; mockFileService.Setup( service => service.CommitAsync(resourceId, sessionId, fileName, hashForFile, fullFileSize, It.IsAny <IList <FilePart> >())) .ReturnsAsync(commitResult); // act await this.classUnderTest.UploadFileAsync(resourceId, filePath, this.cancellationToken); // assert mockFileService.Verify( service => service.CheckFileAsync(1), Times.Once); mockFileService.Verify( service => service.CreateNewUploadSessionAsync(resourceId), Times.Once); mockFileService.Verify( service => service.UploadStreamAsync(resourceId, sessionId, It.IsAny <Stream>(), It.IsAny <FilePart>(), fileName, fullFileSize, countOfFileParts), Times.Exactly(countOfFileParts)); mockFileService.Verify( service => service.CommitAsync(resourceId, sessionId, fileName, hashForFile, fullFileSize, It.IsAny <IList <FilePart> >()), Times.Once); }