using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Model.Services; using Microsoft.Net.Http.Headers; namespace Emby.Server.Implementations.HttpServer { /// /// Class StreamWriter. /// public class StreamWriter : IAsyncStreamWriter, IHasHeaders { /// /// The options. /// private readonly IDictionary _options = new Dictionary(); /// /// Initializes a new instance of the class. /// /// The source. /// Type of the content. public StreamWriter(Stream source, string contentType) { if (string.IsNullOrEmpty(contentType)) { throw new ArgumentNullException(nameof(contentType)); } SourceStream = source; Headers["Content-Type"] = contentType; if (source.CanSeek) { Headers[HeaderNames.ContentLength] = source.Length.ToString(CultureInfo.InvariantCulture); } Headers[HeaderNames.ContentType] = contentType; } /// /// Initializes a new instance of the class. /// /// The source. /// Type of the content. /// The content length. public StreamWriter(byte[] source, string contentType, int contentLength) { if (string.IsNullOrEmpty(contentType)) { throw new ArgumentNullException(nameof(contentType)); } SourceBytes = source; Headers[HeaderNames.ContentLength] = contentLength.ToString(CultureInfo.InvariantCulture); Headers[HeaderNames.ContentType] = contentType; } /// /// Gets or sets the source stream. /// /// The source stream. private Stream SourceStream { get; set; } private byte[] SourceBytes { get; set; } /// /// Gets the options. /// /// The options. public IDictionary Headers => _options; /// /// Fires when complete. /// public Action OnComplete { get; set; } /// /// Fires when an error occours. /// public Action OnError { get; set; } /// public async Task WriteToAsync(Stream responseStream, CancellationToken cancellationToken) { try { var bytes = SourceBytes; if (bytes != null) { await responseStream.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); } else { using (var src = SourceStream) { await src.CopyToAsync(responseStream).ConfigureAwait(false); } } } catch { OnError?.Invoke(); throw; } finally { OnComplete?.Invoke(); } } } }