<PackageReference Include="Relativity.Transfer.Client" Version="6.3.7" />

SoapFileTransferService

using System; using System.IO; using System.Text; using System.Threading; using System.Threading.Tasks; namespace Relativity.Transfer.Http { internal sealed class SoapFileTransferService : ISoapFileTransferService, IDisposable { private readonly IFileSystemService fileSystemService; private readonly RelativityConnectionInfo connectionInfo; private readonly IUserManagerService userManagerService; private readonly IFileIoService fileIoService; private readonly int chunkSize; private readonly bool createDirectories; private bool disposed; private readonly ITransferLog logger; public SoapFileTransferService(RelativityConnectionInfo connectionInfo, Workspace workspace, HttpClientConfiguration configuration, IFileSystemService fileSystemService, ITransferLog log) { if (connectionInfo == null) throw new ArgumentNullException("connectionInfo"); if (configuration == null) throw new ArgumentNullException("configuration"); if (fileSystemService == null) throw new ArgumentNullException("fileSystemService"); if (log == null) throw new ArgumentNullException("log"); this.connectionInfo = connectionInfo; this.fileSystemService = fileSystemService; userManagerService = new UserManagerService(this.connectionInfo, configuration, log); fileIoService = new FileIoService(this.connectionInfo, workspace, configuration, userManagerService, log); logger = log; chunkSize = ((configuration.HttpChunkSize > 0) ? configuration.HttpChunkSize : 102400); createDirectories = configuration.CreateDirectories; } ~SoapFileTransferService() { Dispose(false); } public void Login() { userManagerService.Login(); } public Task RemoveTempFile(int workspaceId, string fileGuid, CancellationToken token) { return fileIoService.RemoveTempFile(workspaceId, fileGuid, token); } public async Task<TransferPathResult> UploadAsync(TransferPath path, CancellationToken token, IProgress<LargeFileProgressEventArgs> progress) { if (path == (TransferPath)null) throw new ArgumentNullException("path"); if (string.IsNullOrEmpty(path.TargetPath)) throw new ArgumentNullException("TargetPath"); if (!path.TargetPath.EndsWith("\\")) path.TargetPath += "\\"; TransferPathResult result = new TransferPathResult { Path = path, Status = TransferPathStatus.Started, StartTime = new DateTime?(DateTime.Now) }; if (token.IsCancellationRequested) { result.Status = TransferPathStatus.Canceled; result.EndTime = DateTime.Now; return result; } using (FileStream sourceStream = new FileStream(path.SourcePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { int readLength = DetermineReadLength(sourceStream); string fileName = DetermineFileName(path); long totalBytes = sourceStream.Length; int totalChunks = TransferHelper.CalculateTotalChunks(totalBytes, chunkSize); logger.LogInformation($"""{totalBytes}""{readLength}""{totalChunks}""", Array.Empty<object>()); for (int i = 0; i < totalChunks; i++) { if (token.IsCancellationRequested) { result.Status = TransferPathStatus.Canceled; result.EndTime = DateTime.Now; return result; } byte[] fileData = FileData(sourceStream, i, ref readLength); if (i == 0) { IoResponse ioResponse = await fileIoService.BeginFillAsync(connectionInfo.WorkspaceId, fileData, path.TargetPath, fileName, token).ConfigureAwait(false); if (!ioResponse.Success) throw new IOException(ioResponse.ErrorMessage); fileName = ioResponse.Filename; } else { IoResponse response = await fileIoService.FileFillAsync(connectionInfo.WorkspaceId, fileData, path.TargetPath, fileName, token).ConfigureAwait(false); if (!response.Success) { await fileIoService.RemoveFillAsync(connectionInfo.WorkspaceId, path.TargetPath, fileName, token).ConfigureAwait(false); throw new IOException(response.ErrorMessage); } } result.BytesTransferred += readLength; result.Checksum = string.Empty; progress?.Report(new LargeFileProgressEventArgs(path, result.BytesTransferred, totalBytes, i + 1, totalChunks)); readLength = ((sourceStream.Position + chunkSize > sourceStream.Length) ? Convert.ToInt32(sourceStream.Length - sourceStream.Position) : chunkSize); } result.EndTime = DateTime.Now; result.Status = (token.IsCancellationRequested ? TransferPathStatus.Canceled : TransferPathStatus.Successful); return result; } } public async Task<TransferPathResult> DownloadAsync(TransferPath path, CancellationToken token, IProgress<LargeFileProgressEventArgs> progress) { if (path == (TransferPath)null) throw new ArgumentNullException("path"); if (string.IsNullOrEmpty(path.TargetPath)) throw new ArgumentNullException("TargetPath"); TransferPathResult result = new TransferPathResult { Path = path, Status = TransferPathStatus.Started, StartTime = new DateTime?(DateTime.Now) }; if (token.IsCancellationRequested) { result.Status = TransferPathStatus.Canceled; result.EndTime = DateTime.Now; return result; } string path2 = path.TargetFileName ?? path.SourcePath; string targetFile = Path.Combine(path.TargetPath, path2); if (createDirectories && !Directory.Exists(path.TargetPath)) Directory.CreateDirectory(path.TargetPath); await fileIoService.DownloadFileAsync(targetFile, path, token, progress).ConfigureAwait(false); FileItem fileItem = fileSystemService.GetFileItem(targetFile); result.BytesTransferred = fileItem.Length; result.EndTime = DateTime.Now; result.Status = (token.IsCancellationRequested ? TransferPathStatus.Canceled : TransferPathStatus.Successful); return result; } public async Task<string> GetDiskSpaceReportAsync(int workspaceId, CancellationToken token) { StringBuilder report = new StringBuilder(); string[][] array = await fileIoService.GetDefaultRepositorySpaceReportAsync(workspaceId, token).ConfigureAwait(false); if (array != null) { string[][] array2 = array; foreach (string[] array3 in array2) { if (report.Length > 0) report.AppendLine(); if (array3.Length > 1) report.AppendFormat("{0}: {1}", array3[0], array3[1]); } } return report.ToString(); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } private void Dispose(bool disposing) { if (!disposed) { if (disposing) { if (userManagerService != null) userManagerService.Dispose(); if (fileIoService != null) fileIoService.Dispose(); } disposed = true; } } private byte[] FileData(Stream sourceStream, int chunkNumber, ref int readLength) { byte[] array = null; int num = 0; try { array = new byte[readLength + 1]; num = (readLength = sourceStream.Read(array, 0, readLength)); return array; } catch (OverflowException) { logger.LogInformation($"""{chunkNumber}", Array.Empty<object>()); logger.LogInformation($"""{readLength}", Array.Empty<object>()); logger.LogInformation($"""{num}", Array.Empty<object>()); logger.LogInformation((array != null) ? $"""{array.Length}" : "Buffer was not initialized.", Array.Empty<object>()); throw; } } private int DetermineReadLength(Stream sourceStream) { int result = chunkSize; if (sourceStream.Length < chunkSize) result = Convert.ToInt32(sourceStream.Length); return result; } private string DetermineFileName(TransferPath path) { if (!string.IsNullOrEmpty(path.TargetFileName)) return path.TargetFileName; string fileName = fileSystemService.GetFileName(path.TargetPath); if (!string.IsNullOrEmpty(fileName)) return fileName; return Guid.NewGuid().ToString(); } } }