private async Task <ReadFileResult> ReadFile(int length) { IBuffer content = bufferAllocator.Allocate(length); Stream dest = content.GetStream(); IMD5HashProvider chunkHash = MD5HashProviderFactory.GetHashProvider().CreateHash(); byte[] b = ArrayPool <byte> .Shared.Rent(Configuration.BufferSize); try { int read = 0; int toRead = length; do { read = await fileStream.ReadAsync(b, offset : 0, count : Math.Min(b.Length, toRead)).ConfigureAwait(false); toRead -= read; await dest.WriteAsync(b, offset : 0, count : read).ConfigureAwait(false); chunkHash.Append(b, offset: 0, size: read); fileHash.Append(b, offset: 0, size: read); } while (read > 0 && toRead > 0); if (toRead > 0) { throw new Exception($"Expected to read {length} bytes, actual read {length - toRead} bytes"); } chunkHash.Finalize(ArrayPool <byte> .Shared.Rent(0), 0, 0); return(new ReadFileResult { Content = content, Hash = chunkHash.GetComputedHashAsString() }); } catch { content.Dispose(); throw; } finally { ArrayPool <byte> .Shared.Return(b); dest.Dispose(); } }
public async Task <string> Append(Stream chunk, CancellationToken cancellationToken) { IMD5HashProvider chunkHash = NewHash(); byte[] buffer = new byte[bufferSize]; int bytesRead = 0; await fileHashLock.WaitAsync(cancellationToken); try { for (long position = 0; position < chunk.Length; position += bytesRead) { bytesRead = await chunk.ReadAsync(buffer, 0, buffer.Length, cancellationToken); fileHash.Append(buffer, 0, bytesRead); chunkHash.Append(buffer, 0, bytesRead); } } finally { fileHashLock.Release(); } chunkHash.Finalize(zeroBuffer, 0, 0); return(chunkHash.GetComputedHashAsString()); }