aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs')
-rw-r--r--MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs74
1 files changed, 63 insertions, 11 deletions
diff --git a/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs b/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs
index fb4397462..7ac92408b 100644
--- a/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs
+++ b/MediaBrowser.Server.Implementations/HttpServer/RangeRequestWriter.cs
@@ -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.
@@ -169,16 +171,6 @@ namespace MediaBrowser.Server.Implementations.HttpServer
/// <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
{
// Headers only
@@ -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; }