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
                    });
            }
            }
        }
Ejemplo n.º 4
0
        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);
        }