update async stream writing

This commit is contained in:
Luke Pulverenti
2016-07-15 13:13:55 -04:00
parent 61aa25c358
commit 2e91d69d20
9 changed files with 141 additions and 311 deletions

View File

@@ -5,10 +5,12 @@ using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using ServiceStack;
namespace MediaBrowser.Server.Implementations.HttpServer
{
public class RangeRequestWriter : IStreamWriter, IHttpResult
public class RangeRequestWriter : IStreamWriter, IAsyncStreamWriter, IHttpResult
{
/// <summary>
/// Gets or sets the source stream.
@@ -168,16 +170,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// </summary>
/// <param name="responseStream">The response stream.</param>
public void WriteTo(Stream responseStream)
{
WriteToInternal(responseStream);
}
/// <summary>
/// Writes to async.
/// </summary>
/// <param name="responseStream">The response stream.</param>
/// <returns>Task.</returns>
private void WriteToInternal(Stream responseStream)
{
try
{
@@ -237,6 +229,66 @@ namespace MediaBrowser.Server.Implementations.HttpServer
}
}
public async Task WriteToAsync(Stream responseStream)
{
try
{
// Headers only
if (IsHeadRequest)
{
return;
}
using (var source = SourceStream)
{
// If the requested range is "0-", we can optimize by just doing a stream copy
if (RangeEnd >= TotalContentLength - 1)
{
await source.CopyToAsync(responseStream, BufferSize).ConfigureAwait(false);
}
else
{
await CopyToInternalAsync(source, responseStream, RangeLength).ConfigureAwait(false);
}
}
}
catch (IOException ex)
{
throw;
}
catch (Exception ex)
{
_logger.ErrorException("Error in range request writer", ex);
throw;
}
finally
{
if (OnComplete != null)
{
OnComplete();
}
}
}
private async Task CopyToInternalAsync(Stream source, Stream destination, long copyLength)
{
var array = new byte[BufferSize];
int count;
while ((count = await source.ReadAsync(array, 0, array.Length).ConfigureAwait(false)) != 0)
{
var bytesToCopy = Math.Min(count, copyLength);
await destination.WriteAsync(array, 0, Convert.ToInt32(bytesToCopy)).ConfigureAwait(false);
copyLength -= bytesToCopy;
if (copyLength <= 0)
{
break;
}
}
}
public string ContentType { get; set; }
public IRequest RequestContext { get; set; }