using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Apewer.Web
{
/// 表示 API 行为结果,主体为流。
public sealed class StreamResult : HeadResult, IDisposable
{
#region content
/// 主体。
public Stream Stream { get; set; }
/// Content-Length 的值,用于限制输出的最大长度。指定为 -1 时不限长度,输出到流的末尾。
/// Default = -1
public long Length { get; set; }
/// 输出后自动释放流。
public bool AutoDispose { get; set; }
/// 创建结果实例。
/// 要输出的流。
/// 内容类型。
/// 输出后自动释放流。
public StreamResult(Stream stream, string contentType = "application/octet-stream", bool autoDispose = true) : this(200, stream, contentType, -1, autoDispose) { }
/// 创建结果实例。
/// HTTP 状态码。
/// 要输出的流。
/// 内容类型。
/// Content-Length 的值。
/// 输出后自动释放流。
public StreamResult(int status, Stream stream, string contentType = "application/octet-stream", long length = -1, bool autoDispose = true) : base(status)
{
Headers.Add("Content-Type", contentType);
Stream = stream;
Length = length;
AutoDispose = autoDispose;
}
#endregion
#region execute
/// 释放系统资源。
public override void Dispose()
{
if (Stream != null)
{
RuntimeUtility.Dispose(Stream);
Stream = null;
}
}
/// 写入 HTTP 头和主体。
public override void ExecuteResult(ApiContext context)
{
try
{
if (Stream == null || Length == 0L)
{
WriteHead(context, 0);
}
else
{
WriteHead(context, Length);
var writed = 0L;
var capacity = 4096;
var buffer = new byte[capacity];
var body = context.Provider.ResponseBody();
// 限制长度。
if (Length > 0L)
{
var remains = Length;
while (true)
{
var limit = Math.Min((int)remains, capacity);
var read = Stream.Read(buffer, 0, limit);
if (read < 1) break;
body.Write(buffer, 0, read);
writed += read;
remains -= read;
if (remains < 1L) break;
}
}
// 不限制长度,输出到流的末尾。
else
{
while (true)
{
var read = Stream.Read(buffer, 0, capacity);
if (read < 1) break;
body.Write(buffer, 0, read);
writed += read;
}
}
context.Provider.End();
}
}
finally
{
if (AutoDispose) Dispose();
}
}
#endregion
}
}