private FileStreamAndHeaders GetFileStreamAndHeaders(CopyRequest request) { FileStreamAndHeaders result = new FileStreamAndHeaders(); try { result.FileName = request.Name; result.Offset = request.Offset; result.Stream = new FileStream(request.Name, FileMode.Open, FileAccess.Read, FileShare.Read, CopyConstants.BufferSize, FileOptions.Asynchronous | FileOptions.SequentialScan); result.FileSize = result.Stream.Length; Debug.Assert(result.Stream.Position == 0L); result.Stream.Seek(request.Offset, SeekOrigin.Begin); Debug.Assert(result.Stream.Position == request.Offset); result.ChunkSize = CopyConstants.BufferSize; // Decide whether to use compression. if (request.Compression == CopyCompression.Gzip && result.FileSize > CopyConstants.BigSize) { result.Compression = CopyCompression.Gzip; } } catch (Exception e) { result.Error = e; } return(result); }
public override async Task Copy(CopyRequest request, IServerStreamWriter <CopyReply> responseStream, ServerCallContext context) { try { Console.WriteLine($"received request for {request.Name}"); FileStreamAndHeaders streamAndHeaders = GetFileStreamAndHeaders(request); using (streamAndHeaders.Stream) { await context.WriteResponseHeadersAsync(streamAndHeaders.GetHeaders()).ConfigureAwait(false); if (streamAndHeaders.Error is null) { Debug.Assert(!(streamAndHeaders.Stream is null)); Debug.Assert(streamAndHeaders.ChunkSize > 0); byte[] buffer = new byte[streamAndHeaders.ChunkSize]; long chunks, bytes; switch (streamAndHeaders.Compression) { case CopyCompression.None: (chunks, bytes) = await StreamContent(streamAndHeaders.Stream, buffer, responseStream).ConfigureAwait(false); break; case CopyCompression.Gzip: (chunks, bytes) = await StreamContentWithCompression(streamAndHeaders.Stream, buffer, responseStream).ConfigureAwait(false); break; default: throw new NotSupportedException(); } Console.WriteLine($"wrote {bytes} bytes in {chunks} chunks"); } } } catch (Exception e) { Console.WriteLine(e); throw; } }