You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
120 lines
3.9 KiB
120 lines
3.9 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
|
|
namespace Apewer.Web
|
|
{
|
|
|
|
/// <summary>表示 API 行为结果,主体为流。</summary>
|
|
public sealed class StreamResult : HeadResult, IDisposable
|
|
{
|
|
|
|
#region content
|
|
|
|
/// <summary>主体。</summary>
|
|
public Stream Stream { get; set; }
|
|
|
|
/// <summary>Content-Length 的值,用于限制输出的最大长度。指定为 -1 时不限长度,输出到流的末尾。</summary>
|
|
/// <value>Default = -1</value>
|
|
public long Length { get; set; }
|
|
|
|
/// <summary>输出后自动释放流。</summary>
|
|
public bool AutoDispose { get; set; }
|
|
|
|
/// <summary>创建结果实例。</summary>
|
|
/// <param name="stream">要输出的流。</param>
|
|
/// <param name="contentType">内容类型。</param>
|
|
/// <param name="autoDispose">输出后自动释放流。</param>
|
|
public StreamResult(Stream stream, string contentType = "application/octet-stream", bool autoDispose = true) : this(200, stream, contentType, -1, autoDispose) { }
|
|
|
|
/// <summary>创建结果实例。</summary>
|
|
/// <param name="status">HTTP 状态码。</param>
|
|
/// <param name="stream">要输出的流。</param>
|
|
/// <param name="contentType">内容类型。</param>
|
|
/// <param name="length">Content-Length 的值。</param>
|
|
/// <param name="autoDispose">输出后自动释放流。</param>
|
|
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
|
|
|
|
/// <summary>释放系统资源。</summary>
|
|
public override void Dispose()
|
|
{
|
|
if (Stream != null)
|
|
{
|
|
RuntimeUtility.Dispose(Stream);
|
|
Stream = null;
|
|
}
|
|
}
|
|
|
|
/// <summary>写入 HTTP 头和主体。</summary>
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|