/// <summary> /// Copy file /// </summary> /// <param name="request">Request. <see cref="CopyFileRequest" /></param> public void CopyFile(CopyFileRequest request) { // verify the required parameter 'srcPath' is set if (request.SrcPath == null) { throw new ApiException(400, "Missing required parameter 'srcPath' when calling CopyFile"); } // create path and map variables var resourcePath = this.configuration.GetApiRootUrl() + "/assembly/storage/file/copy/{srcPath}"; resourcePath = Regex .Replace(resourcePath, "\\*", string.Empty) .Replace("&", "&") .Replace("/?", "?"); resourcePath = UrlHelper.AddPathParameter(resourcePath, "srcPath", request.SrcPath); resourcePath = UrlHelper.AddQueryParameterToUrl(resourcePath, "destPath", request.DestPath); resourcePath = UrlHelper.AddQueryParameterToUrl(resourcePath, "srcStorageName", request.SrcStorageName); resourcePath = UrlHelper.AddQueryParameterToUrl(resourcePath, "destStorageName", request.DestStorageName); resourcePath = UrlHelper.AddQueryParameterToUrl(resourcePath, "versionId", request.VersionId); var response = this.apiInvoker.InvokeApi( resourcePath, "PUT", null, null, null); }
/// <summary> /// Creates a new file by copying from an existing file. /// </summary> /// <exception cref="AuthenticationException">Thrown when authentication fails.</exception> /// <exception cref="CapExceededExecption">Thrown when a cap is exceeded or an account in bad standing.</exception> /// <exception cref="ApiException">Thrown when an error occurs during client operation.</exception> async Task <IApiResults <CopyFileResponse> > IStorageFiles.CopyAsync (string sourceFileId, string fileName) { var request = new CopyFileRequest(sourceFileId, fileName); return(await _client.CopyFileAsync(request, _cancellationToken)); }
public void TestCopyMoveFile() { var testFile = TestFiles.Docx; // Create temp folder var cRequest = new CreateFolderRequest("temp"); FolderApi.CreateFolder(cRequest); // Copy file var destPath = $"temp/{testFile.FileName}"; var request = new CopyFileRequest(testFile.FullName, destPath); FileApi.CopyFile(request); // Check copied file var eRequest = new ObjectExistsRequest(destPath); var eResponse = StorageApi.ObjectExists(eRequest); Assert.IsTrue(eResponse.Exists); // Move file var newDestPath = $"temp/{testFile.FileName.Replace(".", "_1.")}"; var mRequest = new MoveFileRequest(destPath, newDestPath); FileApi.MoveFile(mRequest); // Check moved file eRequest = new ObjectExistsRequest(newDestPath); eResponse = StorageApi.ObjectExists(eRequest); Assert.IsTrue(eResponse.Exists); // Delete temp folder var delRequest = new DeleteFolderRequest("temp", null, true); FolderApi.DeleteFolder(delRequest); }
/// <summary> /// Implements a copy file request. /// </summary> public async Task CopyFile(CopyFileRequest request, IServerStreamWriter <CopyFileResponse> responseStream, ServerCallContext context) { LogRequestHandling(); DateTime startTime = DateTime.UtcNow; var cacheContext = new Context(new Guid(request.TraceId), _logger); if (!_nameByDrive.TryGetValue(request.Drive, out string name)) { await responseStream.WriteAsync( new CopyFileResponse { Header = new ResponseHeader(startTime, false, (int)CopyFileResult.ResultCode.SourcePathError, $"'{request.Drive}' is an invalid cache."), Content = null }); } if (!_contentStoreByCacheName.TryGetValue(name, out var cache)) { await responseStream.WriteAsync( new CopyFileResponse { Header = new ResponseHeader(startTime, false, (int)CopyFileResult.ResultCode.SourcePathError, $"'{name}' is an invalid cache name."), Content = null }); } if (!(cache is IStreamStore copyStore)) { await responseStream.WriteAsync( new CopyFileResponse { Header = new ResponseHeader(startTime, false, (int)CopyFileResult.ResultCode.SourcePathError, $"'{request.Drive}' does not support copying."), Content = null }); return; } var openStreamResult = await copyStore.StreamContentAsync(cacheContext, request.ContentHash.ToContentHash((HashType)request.HashType)); if (openStreamResult.Succeeded) { await StreamContentAsync(openStreamResult, responseStream, startTime); } else { await responseStream.WriteAsync( new CopyFileResponse { Header = new ResponseHeader(startTime, false, (int)openStreamResult.Code, openStreamResult.ErrorMessage, openStreamResult.Diagnostics), Content = null }); } }
public void Test_CopyFileEntry_Success() { var request = new CopyFileRequest(FakeToken, FakeRepoId, "/test/file.txt", FakeRepoId, "/newdir/"); var message = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent("\"success\"") }; Assert.IsTrue(request.WasSuccessful(message)); }
private static async Task CopyFileTest(StorageService.StorageServiceClient client) { Console.WriteLine($"\nCalling 'CopyFile'..."); var request = new CopyFileRequest() { Source = @"C:\Temp\data.bin", Target = @"C:\Temp\data_copy.bin" }; var result = await client.CopyFileAsync(request); Console.WriteLine($"\tFile {request.Source} copied to {result.Path}"); }
/// <summary> /// Copy the given file /// </summary> /// <param name="libraryId">The id of the library the file is in</param> /// <param name="filePath">The full path of the file</param> /// <param name="targetLibraryId">The id of the library to copy this file to</param> /// <param name="targetDirectory">The directory to copy this file to</param> /// <returns>A value which indicates if the action was successful</returns> public async Task <bool> CopyFile(string libraryId, string filePath, string targetLibraryId, string targetDirectory) { libraryId.ThrowOnNull(nameof(libraryId)); filePath.ThrowOnNull(nameof(filePath)); targetLibraryId.ThrowOnNull(nameof(targetLibraryId)); targetDirectory.ThrowOnNull(nameof(targetDirectory)); var request = new CopyFileRequest(AuthToken, libraryId, filePath, targetLibraryId, targetDirectory); return(await _webConnection.SendRequestAsync(ServerUri, request)); }
/// <summary> /// Copy file /// </summary> /// <param name="request">Request. <see cref="CopyFileRequest" /></param> /// <returns><see cref=""/></returns> public void CopyFile(CopyFileRequest request) { // verify the required parameter 'srcPath' is set if (request.srcPath == null) { throw new ApiException(400, "Missing required parameter 'srcPath' when calling CopyFile"); } // verify the required parameter 'destPath' is set if (request.destPath == null) { throw new ApiException(400, "Missing required parameter 'destPath' when calling CopyFile"); } // create path and map variables var resourcePath = this.configuration.GetApiRootUrl() + "/ocr/storage/file/copy/{srcPath}"; resourcePath = Regex .Replace(resourcePath, "\\*", string.Empty) .Replace("&", "&") .Replace("/?", "?"); resourcePath = UrlHelper.AddPathParameter(resourcePath, "srcPath", request.srcPath); resourcePath = UrlHelper.AddQueryParameterToUrl(resourcePath, "destPath", request.destPath); resourcePath = UrlHelper.AddQueryParameterToUrl(resourcePath, "srcStorageName", request.srcStorageName); resourcePath = UrlHelper.AddQueryParameterToUrl(resourcePath, "destStorageName", request.destStorageName); resourcePath = UrlHelper.AddQueryParameterToUrl(resourcePath, "versionId", request.versionId); try { var response = this.apiInvoker.InvokeApi <string>( resourcePath, "PUT", null, null, null); if (response != null) { return; } return; } catch (ApiException ex) { if (ex.ErrorCode == 404) { return; } throw; } }
public void Test_CopyFileEntry_Error() { var request = new CopyFileRequest(FakeToken, FakeRepoId, "/test/file.txt", FakeRepoId, "/newdir/"); var message = new HttpResponseMessage(HttpStatusCode.Forbidden); Assert.IsFalse(request.WasSuccessful(message)); message = new HttpResponseMessage(HttpStatusCode.BadRequest); Assert.IsFalse(request.WasSuccessful(message)); message = new HttpResponseMessage(HttpStatusCode.InternalServerError); Assert.IsFalse(request.WasSuccessful(message)); }
public override Task <CopyFileResponse> CopyFile(CopyFileRequest request, ServerCallContext context) { _logger.LogDebug($"Copying file {request.Source} to {request.Target}..."); return(Task.Run(() => { var file = new FileInfo(request.Source); file.CopyTo(request.Target, true); return new CopyFileResponse() { Path = request.Target }; })); }
public static void Run() { var apiInstance = new FileApi(Constants.GetConfig()); try { var request = new CopyFileRequest("one-page.docx", "one-page-copied.docx", Constants.MyStorage, Constants.MyStorage); apiInstance.CopyFile(request); Console.WriteLine("Expected response type is Void: 'one-page.docx' file copied as 'one-page-copied.docx'."); } catch (Exception e) { Console.WriteLine("Exception while calling FileApi: " + e.Message); } }
public async Task <File> CopyFile(string key, string storageService = null, string asUserKey = null, string bearerToken = null, bool logToConsole = true) { var copyKey = GenerateKey("file"); var copyFileRequest = new CopyFileRequest() { Key = copyKey, StorageService = storageService }; var copyOfFile = await Put <CopyFileRequest, File>(copyFileRequest, $"files/{key}/copy", asUserKey, bearerToken); if (logToConsole) { Console.WriteLine($"Created Copy of File: OriginalKey='{key}', CopyKey='{copyOfFile.Key}'"); } ; return(copyOfFile); }
public async Task <IActionResult> Copy(string fileKey, [FromBody] CopyFileRequest request) { try { var userKey = _contextAccessor.UserKeyFromContext(); bool userCanAccessFile = await UserCanAccessFile(userKey, fileKey, _hiarcDatabase, AccessLevelGroup.ReadOnlyOrHigher); if (userCanAccessFile) { var latestFileVersion = await _hiarcDatabase.GetLatestVersionForFile(fileKey); var sourceStorageService = _storageServiceProvider.Service(latestFileVersion.StorageService); var destinationStorageService = _storageServiceProvider.Service(request.StorageService); IFileInformation versionInfo; if (sourceStorageService.Type == destinationStorageService.Type) { versionInfo = await sourceStorageService.CopyFileToSameServiceType(latestFileVersion.StorageId, destinationStorageService); } else { using var stream = await sourceStorageService.RetrieveFile(latestFileVersion.StorageId); versionInfo = await destinationStorageService.StoreFile(stream); } var newFileRequest = new CreateFileRequest() { Key = request.Key, StorageService = destinationStorageService.Name }; var copyOfFile = await _hiarcDatabase.CreateFile(newFileRequest, userKey, versionInfo.StorageIdentifier); var uri = $"{_hiarcSettings.BaseUri}/files/{copyOfFile.Key}"; return(Created(uri, copyOfFile)); } else { return(StatusCode(StatusCodes.Status403Forbidden)); } } catch (Exception ex) { return(BuildErrorResponse(ex, _logger)); } }
public static void Run() { var configuration = new Configuration(Common.MyAppSid, Common.MyAppKey); var apiInstance = new FileApi(configuration); try { var request = new CopyFileRequest("viewerdocs/one-page1.docx", "viewerdocs/one-page-copied.docx", Common.MyStorage, Common.MyStorage); apiInstance.CopyFile(request); Console.WriteLine("Expected response type is Void: 'viewerdocs/one-page1.docx' file copied as 'viewerdocs/one-page-copied.docx'."); } catch (Exception e) { Console.WriteLine("Exception while calling FileApi: " + e.Message); } }
public void SerializingCopyFileRequest() { var request = new CopyFileRequest() { Source = "a", Target = "bcя" }; var bytes = Google.Protobuf.MessageExtensions.ToByteArray(request); var expected = new byte[] { 10, 1, 97, 18, 4, 98, 99, 209, 143 }; Assert.Equal(expected, bytes); var deserialized = CopyFileRequest.Parser.ParseFrom(bytes); Assert.Equal("a", deserialized.Source); Assert.Equal("bcя", deserialized.Target); }
public void TestCopyFile() { string remoteFileName = "TestCopyFileSrc.docx"; this.UploadFileToStorage( remoteDataFolder + "/" + remoteFileName, null, null, File.ReadAllBytes(LocalTestDataFolder + localFile) ); var request = new CopyFileRequest( destPath: remoteDataFolder + "/TestCopyFileDest.docx", srcPath: remoteDataFolder + "/" + remoteFileName ); this.WordsApi.CopyFile(request); }
public async Task <FileSystemInfoContract> CopyItemAsync(RootName root, FileSystemId source, string copyName, DirectoryId destination, bool recurse) { var context = await RequireContextAsync(root); var path = !string.IsNullOrEmpty(copyName) ? destination.Value.TrimEnd('/') + '/' + copyName : destination.Value; var copyRequest = new CopyFileRequest() { From = source.Value, Path = path }; var link = await context.Client.Commands.CopyAsync(copyRequest, CancellationToken.None); if (!await OperationProgressAsync(context, link)) { throw new ApplicationException(string.Format(CultureInfo.CurrentCulture, Properties.Resources.OperationFailed, nameof(YandexDisk.Client.Clients.ICommandsClient.CopyAsync))); } var request = new ResourceRequest() { Path = path }; var item = await context.Client.MetaInfo.GetInfoAsync(request, CancellationToken.None); return(item.ToFileSystemInfoContract()); }
public void StorageCopyMoveFile() { var testFile = TestFiles.PdfStorage.FirstOrDefault(x => x.Name.Equals("01_pages.pdf")); // Create temp folder var cRequest = new CreateFolderRequest("temp"); FolderApi.CreateFolder(cRequest); // Copy file var destPath = $"temp/{testFile.Name}"; var request = new CopyFileRequest(testFile.Path, destPath); FileApi.CopyFile(request); // Check copied file var eRequest = new ObjectExistsRequest(destPath); var eResponse = StorageApi.ObjectExists(eRequest); Assert.IsTrue(eResponse.Exists); // Move file var newDestPath = $"temp/{testFile.Path.Replace(".", "_1.")}"; var mRequest = new MoveFileRequest(destPath, newDestPath); FileApi.MoveFile(mRequest); // Check moved file eRequest = new ObjectExistsRequest(newDestPath); eResponse = StorageApi.ObjectExists(eRequest); Assert.IsTrue(eResponse.Exists); // Delete temp folder var delRequest = new DeleteFolderRequest("temp", null, true); FolderApi.DeleteFolder(delRequest); }
/// <summary> /// Creates a new file by copying from an existing file. /// </summary> /// <param name="request">The <see cref="CopyFileRequest"/> to send.</param> /// <exception cref="AuthenticationException">Thrown when authentication fails.</exception> /// <exception cref="CapExceededExecption">Thrown when a cap is exceeded or an account in bad standing.</exception> /// <exception cref="ApiException">Thrown when an error occurs during client operation.</exception> async Task <IApiResults <CopyFileResponse> > IStorageFiles.CopyAsync (CopyFileRequest request) { return(await _client.CopyFileAsync(request, _cancellationToken)); }
public static Task CopyAndWaitAsync([NotNull] this ICommandsClient client, [NotNull] CopyFileRequest request, CancellationToken cancellationToken, int pullPeriod) { return(CopyAndWaitAsync(client, request, cancellationToken, TimeSpan.FromSeconds(pullPeriod))); }
/// <summary> /// Copies content from the server to the stream returned by the factory. /// </summary> private async Task <CopyFileResult> CopyToCoreAsync(OperationContext context, ContentHash hash, Func <Stream> streamFactory) { try { CopyFileRequest request = new CopyFileRequest() { TraceId = context.TracingContext.Id.ToString(), HashType = (int)hash.HashType, ContentHash = hash.ToByteString(), Offset = 0, Compression = Key.UseCompression ? CopyCompression.Gzip : CopyCompression.None }; AsyncServerStreamingCall <CopyFileResponse> response = _client.CopyFile(request); Metadata headers = await response.ResponseHeadersAsync; // If the remote machine couldn't be contacted, GRPC returns an empty // header collection. GRPC would throw an RpcException when we tried // to stream response, but by that time we would have created target // stream. To avoid that, exit early instead. if (headers.Count == 0) { return(new CopyFileResult(CopyFileResult.ResultCode.SourcePathError, $"Failed to connect to copy server {Key.Host} at port {Key.GrpcPort}.")); } // Parse header collection. string exception = null; string message = null; CopyCompression compression = CopyCompression.None; foreach (Metadata.Entry header in headers) { switch (header.Key) { case "exception": exception = header.Value; break; case "message": message = header.Value; break; case "compression": Enum.TryParse(header.Value, out compression); break; } } // Process reported server-side errors. if (exception != null) { Contract.Assert(message != null); switch (exception) { case "ContentNotFound": return(new CopyFileResult(CopyFileResult.ResultCode.FileNotFoundError, message)); default: return(new CopyFileResult(CopyFileResult.ResultCode.SourcePathError, message)); } } // We got headers back with no errors, so create the target stream. Stream targetStream; try { targetStream = streamFactory(); } catch (Exception targetException) { return(new CopyFileResult(CopyFileResult.ResultCode.DestinationPathError, targetException)); } // Copy the content to the target stream. using (targetStream) { switch (compression) { case CopyCompression.None: await StreamContentAsync(targetStream, response.ResponseStream, context.Token); break; case CopyCompression.Gzip: await StreamContentWithCompressionAsync(targetStream, response.ResponseStream, context.Token); break; default: throw new NotSupportedException($"CopyCompression {compression} is not supported."); } } return(CopyFileResult.Success); } catch (RpcException r) { if (r.StatusCode == StatusCode.Unavailable) { return(new CopyFileResult(CopyFileResult.ResultCode.SourcePathError, r)); } else { return(new CopyFileResult(CopyFileResult.ResultCode.Unknown, r)); } } }
/// <summary> /// Copy file or folder on Disk from one path to another and wait until operation is done /// </summary> public static async Task CopyAndWaitAsync([NotNull] this ICommandsClient client, [NotNull] CopyFileRequest request, CancellationToken cancellationToken = default(CancellationToken), TimeSpan?pullPeriod = null) { var link = await client.CopyAsync(request, cancellationToken).ConfigureAwait(false); if (link.HttpStatusCode == HttpStatusCode.Accepted) { await client.WaitOperationAsync(link, cancellationToken, pullPeriod).ConfigureAwait(false); } }
/// <summary> /// Converts a <see cref="CopyFileRequest"/> to a <see cref="ContentHash"/>. /// </summary> public static ContentHash GetContentHash(this CopyFileRequest request) => request.ContentHash.ToContentHash((HashType)request.HashType);
private async Task <CopyFileResult> CopyToCoreAsync(OperationContext context, ContentHash hash, CopyOptions options, Func <Stream> streamFactory, bool closeStream) { using var cts = CancellationTokenSource.CreateLinkedTokenSource(context.Token); var token = cts.Token; bool exceptionThrown = false; TimeSpan? headerResponseTime = null; CopyFileResult?result = null; try { CopyFileRequest request = new CopyFileRequest() { TraceId = context.TracingContext.Id.ToString(), HashType = (int)hash.HashType, ContentHash = hash.ToByteString(), Offset = 0, Compression = _configuration.UseGzipCompression ? CopyCompression.Gzip : CopyCompression.None, FailFastIfBusy = options.BandwidthConfiguration?.FailFastIfServerIsBusy ?? false, }; using AsyncServerStreamingCall <CopyFileResponse> response = _client.CopyFile(request, options: GetDefaultGrpcOptions(token)); Metadata headers; var stopwatch = StopwatchSlim.Start(); try { var connectionTimeout = GetResponseHeadersTimeout(options); headers = await response.ResponseHeadersAsync.WithTimeoutAsync(connectionTimeout, token); headerResponseTime = stopwatch.Elapsed; } catch (TimeoutException t) { // Trying to cancel the back end operation as well. cts.Cancel(); result = new CopyFileResult(GetCopyResultCodeForGetResponseHeaderTimeout(), t); return(result); } // If the remote machine couldn't be contacted, GRPC returns an empty // header collection. GRPC would throw an RpcException when we tried // to stream response, but by that time we would have created target // stream. To avoid that, exit early instead. if (headers.Count == 0) { result = new CopyFileResult( CopyResultCode.ServerUnavailable, $"Failed to connect to copy server {Key.Host} at port {Key.GrpcPort}."); return(result); } // Parse header collection. string? exception = null; string? message = null; CopyCompression compression = CopyCompression.None; foreach (Metadata.Entry header in headers) { switch (header.Key) { case "exception": exception = header.Value; break; case "message": message = header.Value; break; case "compression": Enum.TryParse(header.Value, out compression); break; } } // Process reported server-side errors. if (exception != null) { Contract.Assert(message != null); switch (exception) { case "ContentNotFound": result = new CopyFileResult(CopyResultCode.FileNotFoundError, message); return(result); default: result = new CopyFileResult(CopyResultCode.UnknownServerError, message); return(result); } } // We got headers back with no errors, so create the target stream. Stream targetStream; try { targetStream = streamFactory(); } catch (Exception targetException) { result = new CopyFileResult(CopyResultCode.DestinationPathError, targetException); return(result); } result = await _bandwidthChecker.CheckBandwidthAtIntervalAsync( context, innerToken => copyToCoreImplementation(response, compression, targetStream, innerToken), options, getErrorResult : diagnostics => new CopyFileResult(CopyResultCode.CopyBandwidthTimeoutError, diagnostics)); return(result); } catch (RpcException r) { result = CreateResultFromException(r); return(result); } catch (Exception) { exceptionThrown = true; throw; } finally { // Even though we don't expect exceptions in this method, we can't assume they won't happen. // So asserting that the result is not null only when the method completes successfully or with a known errors. Contract.Assert(exceptionThrown || result != null); if (result != null) { result.HeaderResponseTime = headerResponseTime; } } async Task <CopyFileResult> copyToCoreImplementation(AsyncServerStreamingCall <CopyFileResponse> response, CopyCompression compression, Stream targetStream, CancellationToken token) { // Copy the content to the target stream. try { switch (compression) { case CopyCompression.None: await StreamContentAsync(response.ResponseStream, targetStream, options, token); break; case CopyCompression.Gzip: await StreamContentWithCompressionAsync(response.ResponseStream, targetStream, options, token); break; default: throw new NotSupportedException($"CopyCompression {compression} is not supported."); } } finally { if (closeStream) { #pragma warning disable AsyncFixer02 // A disposable object used in a fire & forget async call targetStream.Dispose(); #pragma warning restore AsyncFixer02 // A disposable object used in a fire & forget async call } } return(CopyFileResult.Success); } }
public void Copy(CopyFileRequest args) { Console.WriteLine($"Copy - {JsonConvert.SerializeObject(args)}"); }
public Task <Link> CopyAsync(CopyFileRequest request, CancellationToken cancellationToken = default) { return(PostAsync <CopyFileRequest, object, Link>("resources/copy", request, /*requestBody*/ null, cancellationToken)); }
/// <summary> /// Implements a copy file request. /// </summary> private async Task CopyFileAsync(CopyFileRequest request, IServerStreamWriter <CopyFileResponse> responseStream, ServerCallContext context) { OperationStarted(); // Get the content stream. Context cacheContext = new Context(new Guid(request.TraceId), Logger); ContentHash hash = request.GetContentHash(); OpenStreamResult result = await GetFileStreamAsync(cacheContext, hash); // If result is unsuccessful, then result.Stream is null, but using(null) is just a no op. using (result.Stream) { // Figure out response headers. CopyCompression compression = CopyCompression.None; Metadata headers = new Metadata(); switch (result.Code) { case OpenStreamResult.ResultCode.ContentNotFound: headers.Add("Exception", "ContentNotFound"); headers.Add("Message", $"Requested content at {hash} not found."); break; case OpenStreamResult.ResultCode.Error: Contract.Assert(result.Exception != null); headers.Add("Exception", result.Exception.GetType().Name); headers.Add("Message", result.Exception.Message); break; case OpenStreamResult.ResultCode.Success: Contract.Assert(result.Stream != null); long size = result.Stream.Length; headers.Add("FileSize", size.ToString()); if ((request.Compression == CopyCompression.Gzip) && (size > _gzipSizeBarrier)) { compression = CopyCompression.Gzip; } headers.Add("Compression", compression.ToString()); headers.Add("ChunkSize", _bufferSize.ToString()); break; default: throw new NotImplementedException($"Unknown result.Code '{result.Code}'."); } // Send the response headers. await context.WriteResponseHeadersAsync(headers); // Send the content. if (result.Succeeded) { var operationContext = new OperationContext(cacheContext, context.CancellationToken); using (var arrayHandle = _pool.Get()) { StreamContentDelegate streamContent = compression == CopyCompression.None ? (StreamContentDelegate)StreamContentAsync : StreamContentWithCompressionAsync; byte[] buffer = arrayHandle.Value; await operationContext.PerformOperationAsync( _tracer, () => streamContent(result.Stream, buffer, responseStream, context.CancellationToken), traceOperationStarted : false, // Tracing only stop messages extraEndMessage : r => $"Hash={hash.ToShortString()}, GZip={(compression == CopyCompression.Gzip ? "on" : "off")}.") .IgnoreFailure(); // The error was already logged. } } } }
/// <inheritdoc /> public override Task CopyFile(CopyFileRequest request, IServerStreamWriter <CopyFileResponse> responseStream, ServerCallContext context) => _contentServer.CopyFileAsync(request, responseStream, context);
/// <summary> /// Implements a copy file request. /// </summary> private async Task CopyFileAsync(CopyFileRequest request, IServerStreamWriter <CopyFileResponse> responseStream, ServerCallContext context) { try { LogRequestHandling(); // Get the content stream. Context cacheContext = new Context(new Guid(request.TraceId), _logger); HashType type = (HashType)request.HashType; ContentHash hash = request.ContentHash.ToContentHash((HashType)request.HashType); OpenStreamResult result = await GetFileStreamAsync(cacheContext, hash); using (result.Stream) { // Figure out response headers. CopyCompression compression = CopyCompression.None; Metadata headers = new Metadata(); switch (result.Code) { case OpenStreamResult.ResultCode.ContentNotFound: headers.Add("Exception", "ContentNotFound"); headers.Add("Message", $"Requested content at {hash} not found."); break; case OpenStreamResult.ResultCode.Error: Debug.Assert(result.Exception != null); headers.Add("Exception", result.Exception.GetType().Name); headers.Add("Message", result.Exception.Message); break; case OpenStreamResult.ResultCode.Success: Debug.Assert(result.Stream != null); long size = result.Stream.Length; headers.Add("FileSize", size.ToString()); if ((request.Compression == CopyCompression.Gzip) && (size > _bufferSize)) { compression = CopyCompression.Gzip; } headers.Add("Compression", compression.ToString()); headers.Add("ChunkSize", _bufferSize.ToString()); break; default: throw new NotImplementedException(); } // Send the response headers. await context.WriteResponseHeadersAsync(headers); // Send the content. if (result.Succeeded) { _logger.Debug($"Streaming file through GRPC with GZip {(compression == CopyCompression.Gzip ? "on" : "off")}"); byte[] buffer = new byte[_bufferSize]; switch (compression) { case CopyCompression.None: await StreamContentAsync(result.Stream, buffer, responseStream, context.CancellationToken); break; case CopyCompression.Gzip: await StreamContentWithCompressionAsync(result.Stream, buffer, responseStream, context.CancellationToken); break; } } } } catch (Exception) { throw; } }