diff --git a/src/Microsoft.AspNet.Http.Extensions/SendFileResponseExtensions.cs b/src/Microsoft.AspNet.Http.Extensions/SendFileResponseExtensions.cs index bb236b7dd0..747e91096e 100644 --- a/src/Microsoft.AspNet.Http.Extensions/SendFileResponseExtensions.cs +++ b/src/Microsoft.AspNet.Http.Extensions/SendFileResponseExtensions.cs @@ -5,6 +5,7 @@ using System; using System.IO; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNet.Http.Extensions; using Microsoft.AspNet.Http.Features; namespace Microsoft.AspNet.Http @@ -96,10 +97,7 @@ namespace Microsoft.AspNet.Http { fileStream.Seek(offset, SeekOrigin.Begin); - // TODO: Use buffer pool - var buffer = new byte[bufferSize]; - - await StreamCopyOperation.CopyToAsync(fileStream, buffer, outputStream, length, cancel); + await StreamCopyOperation.CopyToAsync(fileStream, outputStream, length, cancel); } } } diff --git a/src/Microsoft.AspNet.Http.Extensions/StreamCopyOperation.cs b/src/Microsoft.AspNet.Http.Extensions/StreamCopyOperation.cs index f7e6734c9c..a59aed1f0a 100644 --- a/src/Microsoft.AspNet.Http.Extensions/StreamCopyOperation.cs +++ b/src/Microsoft.AspNet.Http.Extensions/StreamCopyOperation.cs @@ -2,55 +2,67 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Buffers; using System.Diagnostics; using System.IO; using System.Threading; using System.Threading.Tasks; -namespace Microsoft.AspNet.Http +namespace Microsoft.AspNet.Http.Extensions { // FYI: In most cases the source will be a FileStream and the destination will be to the network. - internal static class StreamCopyOperation + public static class StreamCopyOperation { - internal static async Task CopyToAsync(Stream source, byte[] buffer, Stream destination, long? length, CancellationToken cancel) + private const int DefaultBufferSize = 4096; + + public static async Task CopyToAsync(Stream source, Stream destination, long? length, CancellationToken cancel) { long? bytesRemaining = length; - Debug.Assert(source != null); - Debug.Assert(destination != null); - Debug.Assert(!bytesRemaining.HasValue || bytesRemaining.Value >= 0); - Debug.Assert(buffer != null); - while (true) + var buffer = ArrayPool.Shared.Rent(DefaultBufferSize); + try { - // The natural end of the range. - if (bytesRemaining.HasValue && bytesRemaining.Value <= 0) + Debug.Assert(source != null); + Debug.Assert(destination != null); + Debug.Assert(!bytesRemaining.HasValue || bytesRemaining.Value >= 0); + Debug.Assert(buffer != null); + + while (true) { - return; + // The natural end of the range. + if (bytesRemaining.HasValue && bytesRemaining.Value <= 0) + { + return; + } + + cancel.ThrowIfCancellationRequested(); + + int readLength = buffer.Length; + if (bytesRemaining.HasValue) + { + readLength = (int)Math.Min(bytesRemaining.Value, (long)readLength); + } + int count = await source.ReadAsync(buffer, 0, readLength, cancel); + + if (bytesRemaining.HasValue) + { + bytesRemaining -= count; + } + + // End of the source stream. + if (count == 0) + { + return; + } + + cancel.ThrowIfCancellationRequested(); + + await destination.WriteAsync(buffer, 0, count, cancel); } - - cancel.ThrowIfCancellationRequested(); - - int readLength = buffer.Length; - if (bytesRemaining.HasValue) - { - readLength = (int)Math.Min(bytesRemaining.Value, (long)readLength); - } - int count = await source.ReadAsync(buffer, 0, readLength, cancel); - - if (bytesRemaining.HasValue) - { - bytesRemaining -= count; - } - - // End of the source stream. - if (count == 0) - { - return; - } - - cancel.ThrowIfCancellationRequested(); - - await destination.WriteAsync(buffer, 0, count, cancel); + } + finally + { + ArrayPool.Shared.Return(buffer); } } } diff --git a/src/Microsoft.AspNet.Http.Extensions/project.json b/src/Microsoft.AspNet.Http.Extensions/project.json index 747d08ca80..8aa5deacf7 100644 --- a/src/Microsoft.AspNet.Http.Extensions/project.json +++ b/src/Microsoft.AspNet.Http.Extensions/project.json @@ -11,7 +11,8 @@ }, "dependencies": { "Microsoft.AspNet.Http.Abstractions": "1.0.0-*", - "Microsoft.Net.Http.Headers": "1.0.0-*" + "Microsoft.Net.Http.Headers": "1.0.0-*", + "System.Buffers": "4.0.0-*" }, "frameworks": { "net451": {},