307 lines
8.9 KiB
C#
307 lines
8.9 KiB
C#
using System.IO;
|
||
using System.Threading.Tasks;
|
||
using System.Collections.Specialized;
|
||
using Microsoft.AspNetCore.Http;
|
||
using System.Text;
|
||
using CYQ.Data;
|
||
using static System.Net.Mime.MediaTypeNames;
|
||
|
||
namespace System.Web
|
||
{
|
||
/// <summary>
|
||
/// 输出对象(单例存在,不该有自己的属性)
|
||
/// </summary>
|
||
public class HttpResponse
|
||
{
|
||
Microsoft.AspNetCore.Http.HttpContext context
|
||
{
|
||
get
|
||
{
|
||
return HttpContext.contextAccessor.HttpContext;
|
||
}
|
||
}
|
||
Microsoft.AspNetCore.Http.HttpResponse response => context.Response;
|
||
|
||
internal HttpResponse()
|
||
{
|
||
|
||
}
|
||
|
||
#region 兼容Web
|
||
public void End()
|
||
{
|
||
if (!context.Items.ContainsKey("IsRunToEnd"))
|
||
{
|
||
context.Items.Add("IsRunToEnd", true);
|
||
}
|
||
}
|
||
private bool IsEnd
|
||
{
|
||
get
|
||
{
|
||
return context.Items.ContainsKey("IsRunToEnd");
|
||
}
|
||
}
|
||
public string Charset
|
||
{
|
||
get
|
||
{
|
||
string ct = ContentType;
|
||
int i = ct.IndexOf("charset=");
|
||
if (i > -1)
|
||
{
|
||
return ct.Substring(i + 8);
|
||
}
|
||
|
||
return "utf-8";
|
||
}
|
||
set
|
||
{
|
||
//Headers are read-only, response has already started
|
||
if (HasStarted) { return; }
|
||
string ct = ContentType;
|
||
if (string.IsNullOrEmpty(ct))
|
||
{
|
||
ContentType = "text/html; charset=" + value.Replace("charset=", "");
|
||
}
|
||
else if (!ct.Contains("charset="))
|
||
{
|
||
ContentType = ct.TrimEnd(';') + "; charset=" + value;
|
||
}
|
||
}
|
||
}
|
||
public string ContentType
|
||
{
|
||
get => response.ContentType ?? "";
|
||
set
|
||
{
|
||
try
|
||
{
|
||
if (response.ContentType != value)
|
||
{
|
||
if (value.Contains("charset") || string.IsNullOrEmpty(response.ContentType))
|
||
{
|
||
response.ContentType = value;
|
||
}
|
||
else
|
||
{
|
||
string[] items = response.ContentType.Split(';');
|
||
if (items.Length == 2)//包含两个,只改前面的,不改编码
|
||
{
|
||
response.ContentType = value + ";" + items[1];
|
||
}
|
||
else if (response.ContentType.Contains("charset"))//只有charset
|
||
{
|
||
response.ContentType = value + "; " + items[0].Trim();
|
||
}
|
||
else//只有text/html
|
||
{
|
||
response.ContentType = value + "; charset=utf-8";
|
||
}
|
||
}
|
||
}
|
||
}
|
||
catch (Exception err)
|
||
{
|
||
Log.Write(err, LogType.Error);
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
public Encoding ContentEncoding
|
||
{
|
||
get
|
||
{
|
||
return Encoding.GetEncoding(Charset);
|
||
}
|
||
set
|
||
{
|
||
Charset = value.WebName;
|
||
}
|
||
}
|
||
|
||
public Stream Filter
|
||
{
|
||
get => Body;
|
||
set
|
||
{
|
||
Body = value;
|
||
}
|
||
}
|
||
|
||
public void AppendHeader(string key, string value)
|
||
{
|
||
if (!response.HasStarted)
|
||
{
|
||
response.Headers.Remove(key);
|
||
response.Headers.Add(key, value);
|
||
}
|
||
}
|
||
//public bool Buffer { get; set; }
|
||
//public int Expires { get; set; }
|
||
//public DateTime ExpiresAbsolute { get; set; }
|
||
public string CacheControl
|
||
{
|
||
get => Headers["Cache-Control"];
|
||
set => AppendHeader("Cache-Control", value);
|
||
}
|
||
|
||
public void Clear() { response.Clear(); }
|
||
public void Flush() { response.Body.Flush(); }
|
||
#endregion
|
||
|
||
|
||
public HttpCookieCollection Cookies
|
||
{
|
||
get
|
||
{
|
||
if (context.Items.ContainsKey("ResponseCookies"))
|
||
{
|
||
return context.Items["ResponseCookies"] as HttpCookieCollection;
|
||
}
|
||
else
|
||
{
|
||
var cookies = new HttpCookieCollection(true);
|
||
context.Items.Add("ResponseCookies", cookies);
|
||
return cookies;
|
||
}
|
||
}
|
||
}
|
||
|
||
public int StatusCode
|
||
{
|
||
get => response.StatusCode; set
|
||
{
|
||
if (!response.HasStarted)
|
||
{
|
||
response.StatusCode = value;
|
||
}
|
||
}
|
||
}
|
||
|
||
public NameValueCollection Headers
|
||
{
|
||
get
|
||
{
|
||
NameValueCollection nvc = new NameValueCollection();
|
||
if (response.Headers != null && response.Headers.Keys.Count > 0)
|
||
{
|
||
foreach (string key in response.Headers.Keys)
|
||
{
|
||
nvc.Add(key, response.Headers[key].ToString());
|
||
}
|
||
}
|
||
return nvc;
|
||
}
|
||
}
|
||
|
||
public Stream Body
|
||
{
|
||
get => response.Body;
|
||
set
|
||
{
|
||
response.Body = value;
|
||
}
|
||
}
|
||
public long? ContentLength { get => response.ContentLength; set => response.ContentLength = value; }
|
||
|
||
/// <summary>
|
||
/// 是否已启用输出:(已输出到客户端 || 已调用Response.End() || 已调用Response.Write())
|
||
/// </summary>
|
||
public bool HasStarted
|
||
{
|
||
get
|
||
{
|
||
return response.HasStarted || IsEnd || context.Items.TryGetValue("CallWrite", out _);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
public void OnCompleted(Func<object, Task> callback, object state)
|
||
{
|
||
response.OnCompleted(callback, state);
|
||
}
|
||
|
||
public void OnStarting(Func<object, Task> callback, object state)
|
||
{
|
||
response.OnStarting(callback, state);
|
||
}
|
||
/// <summary>
|
||
/// 302 跳转
|
||
/// </summary>
|
||
/// <param name="location"></param>
|
||
public void Redirect(string location)
|
||
{
|
||
Redirect(location, false);
|
||
}
|
||
/// <summary>
|
||
/// 跳转
|
||
/// </summary>
|
||
/// <param name="location"></param>
|
||
/// <param name="permanent">true 301跳转,默认false 是302跳转</param>
|
||
public void Redirect(string location, bool permanent)
|
||
{
|
||
if (string.IsNullOrEmpty(location)) { return; }
|
||
if (!location.StartsWith("/") && !location.StartsWith("http://") && !location.StartsWith("https://"))
|
||
{
|
||
string path = context.Request.Path;// microservice/login
|
||
string[] items = path.Trim('/').Split('/');
|
||
items[items.Length - 1] = location;
|
||
location = "/" + string.Join("/", items);
|
||
}
|
||
response.Redirect(location, permanent);
|
||
End();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 内部:异步执行的(未等待)
|
||
/// </summary>
|
||
/// <param name="text"></param>
|
||
public void Write(string text)
|
||
{
|
||
if (!IsEnd)
|
||
{
|
||
SetWriteFlag();
|
||
byte[] data = ContentEncoding.GetBytes(text);
|
||
response.Body.WriteAsync(data, 0, data.Length);
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 内部:异步执行的(并等待结束)
|
||
/// </summary>
|
||
/// <param name="fileName"></param>
|
||
public void WriteFile(string fileName)
|
||
{
|
||
byte[] data = File.ReadAllBytes(fileName);
|
||
if (!IsEnd && data != null)
|
||
{
|
||
SetWriteFlag();
|
||
response.Body.WriteAsync(data, 0, data.Length).Wait();
|
||
End();
|
||
}
|
||
}
|
||
/// <summary>
|
||
/// 内部:异步执行的(并等待结束)
|
||
/// </summary>
|
||
/// <param name="data"></param>
|
||
public void BinaryWrite(byte[] data)
|
||
{
|
||
if (!IsEnd && data != null)
|
||
{
|
||
SetWriteFlag();
|
||
response.Body.WriteAsync(data, 0, data.Length).Wait();
|
||
}
|
||
}
|
||
private void SetWriteFlag()
|
||
{
|
||
if (!context.Items.ContainsKey("CallWrite"))
|
||
{
|
||
context.Items.Add("CallWrite", true);
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|