diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2017-03-12 15:27:26 -0400 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2017-03-12 15:27:26 -0400 |
| commit | a660aa001eb31e91d040e066787fa764cf5f0fb4 (patch) | |
| tree | 0bff0b393b98d1c74cc7383590c3826e95f36aff /SocketHttpListener.Portable/Net/ResponseStream.cs | |
| parent | 29185eb9bd964e800b29282d91c8e36828460eb3 (diff) | |
re-organize file streaming
Diffstat (limited to 'SocketHttpListener.Portable/Net/ResponseStream.cs')
| -rw-r--r-- | SocketHttpListener.Portable/Net/ResponseStream.cs | 84 |
1 files changed, 83 insertions, 1 deletions
diff --git a/SocketHttpListener.Portable/Net/ResponseStream.cs b/SocketHttpListener.Portable/Net/ResponseStream.cs index a79a18791..ccc0efc55 100644 --- a/SocketHttpListener.Portable/Net/ResponseStream.cs +++ b/SocketHttpListener.Portable/Net/ResponseStream.cs @@ -5,6 +5,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Model.IO; +using MediaBrowser.Model.Net; using MediaBrowser.Model.Text; using SocketHttpListener.Primitives; @@ -22,12 +23,18 @@ namespace SocketHttpListener.Net Stream stream; private readonly IMemoryStreamFactory _memoryStreamFactory; private readonly ITextEncoding _textEncoding; + private readonly IFileSystem _fileSystem; + private readonly IAcceptSocket _socket; + private readonly bool _supportsDirectSocketAccess; - internal ResponseStream(Stream stream, HttpListenerResponse response, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding) + internal ResponseStream(Stream stream, HttpListenerResponse response, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem, IAcceptSocket socket, bool supportsDirectSocketAccess) { this.response = response; _memoryStreamFactory = memoryStreamFactory; _textEncoding = textEncoding; + _fileSystem = fileSystem; + _socket = socket; + _supportsDirectSocketAccess = supportsDirectSocketAccess; this.stream = stream; } @@ -299,5 +306,80 @@ namespace SocketHttpListener.Net { throw new NotSupportedException(); } + + public Task TransmitFile(string path, long offset, long count, CancellationToken cancellationToken) + { + //if (_supportsDirectSocketAccess && offset == 0 && count == 0 && !response.SendChunked) + //{ + // return TransmitFileOverSocket(path, offset, count, cancellationToken); + //} + return TransmitFileManaged(path, offset, count, cancellationToken); + } + + private readonly byte[] _emptyBuffer = new byte[] { }; + private async Task TransmitFileOverSocket(string path, long offset, long count, CancellationToken cancellationToken) + { + MemoryStream ms = GetHeaders(response, _memoryStreamFactory, false); + + var buffer = new byte[] {}; + if (ms != null) + { + ms.Position = 0; + + byte[] msBuffer; + _memoryStreamFactory.TryGetBuffer(ms, out msBuffer); + buffer = msBuffer; + } + + await _socket.SendFile(path, buffer, _emptyBuffer, cancellationToken).ConfigureAwait(false); + } + + private async Task TransmitFileManaged(string path, long offset, long count, CancellationToken cancellationToken) + { + var chunked = response.SendChunked; + + if (!chunked) + { + await WriteAsync(_emptyBuffer, 0, 0, cancellationToken).ConfigureAwait(false); + } + + using (var fs = _fileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, FileShareMode.Read, true)) + { + if (offset > 0) + { + fs.Position = offset; + } + + var targetStream = chunked ? this : stream; + + if (count > 0) + { + await CopyToInternalAsync(fs, targetStream, count, cancellationToken).ConfigureAwait(false); + } + else + { + await fs.CopyToAsync(targetStream, 81920, cancellationToken).ConfigureAwait(false); + } + } + } + + private async Task CopyToInternalAsync(Stream source, Stream destination, long copyLength, CancellationToken cancellationToken) + { + var array = new byte[81920]; + int count; + while ((count = await source.ReadAsync(array, 0, array.Length, cancellationToken).ConfigureAwait(false)) != 0) + { + var bytesToCopy = Math.Min(count, copyLength); + + await destination.WriteAsync(array, 0, Convert.ToInt32(bytesToCopy), cancellationToken).ConfigureAwait(false); + + copyLength -= bytesToCopy; + + if (copyLength <= 0) + { + break; + } + } + } } } |
