123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267 |
- using MiniWebApi.Utilities;
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.IO.Compression;
- using System.Linq;
- using System.Net;
- using System.Text;
- using System.Text.RegularExpressions;
- using Vinno.IUS.Common.Log;
- namespace Vinno.vCloud.Disk
- {
- internal class ViewEngine
- {
- public DateTime LastModifiedTime { get; set; }
- private Dictionary<string, string> _fileSourceDic;
- private string _namespace;
- /// <summary>
- /// 是否为局域网内部署
- /// </summary>
- public bool IsLocalServer { get; set; } = false;
- public ViewEngine()
- {
- _namespace = GetType().Namespace;
- _fileSourceDic = new Dictionary<string, string>();
- var fileList = GetType().Assembly.GetManifestResourceNames();
- foreach (string fileName in fileList)
- {
- if (string.IsNullOrWhiteSpace(fileName)) continue;
- if (!fileName.ToLower().StartsWith(_namespace.ToLower())) continue;
- string key = fileName.Substring(_namespace.Length).ToLower();
- _fileSourceDic.Add(key, fileName);
- _fileSourceDic.Add($".{key}", fileName);
- }
- }
- /// <summary>
- /// 获取资源文件
- /// </summary>
- /// <param name="filePath"></param>
- /// <returns></returns>
- public Stream GetResourceFile(string filePath)
- {
- filePath = filePath?.Replace("/", ".").ToLower();
- if (!filePath.StartsWith(".")) filePath = "." + filePath;
- if (!_fileSourceDic.ContainsKey(filePath)) return Stream.Null;
- return GetType().Assembly.GetManifestResourceStream(_fileSourceDic[filePath]);
- }
- /// <summary>
- /// 读取文件
- /// </summary>
- /// <param name="extType"></param>
- /// <param name="model"></param>
- /// <param name="fileStream"></param>
- /// <returns></returns>
- private List<byte> GetFileSource(string extType, object model, Stream fileStream)
- {
- List<byte> byteList = new List<byte>();
- if (fileStream != null)
- {
- using (fileStream)
- {
- byte[] bytes = new byte[8192];
- int readCount = 0;
- do
- {
- readCount = fileStream.Read(bytes, 0, bytes.Length);
- byteList.AddRange(bytes.Take(readCount));
- }
- while (readCount > 0);
- bytes = null;
- }
- }
- return byteList;
- }
- /// <summary>
- /// 获取资源文件
- /// </summary>
- /// <param name="filePath"></param>
- /// <returns></returns>
- private List<byte> GetResourceFile(string filePath, string extType, object model = null)
- {
- filePath = filePath?.Replace("/", ".").ToLower();
- if (!_fileSourceDic.ContainsKey(filePath)) return new List<byte>();
- using (var fileStream = GetType().Assembly.GetManifestResourceStream(_fileSourceDic[filePath]))
- {
- return GetFileSource(extType, model, fileStream);
- }
- }
- /// <summary>
- /// 读取某个路径下的文件
- /// </summary>
- /// <param name="filePath"></param>
- /// <returns></returns>
- private List<byte> GetPathFile(string filePath, string extType, object model = null)
- {
- if (!string.IsNullOrWhiteSpace(filePath))
- {
- var currentDir = AppDomain.CurrentDomain.BaseDirectory;
- filePath = Path.Combine(currentDir, filePath.Replace("/", "\\"));
- if (File.Exists(filePath))
- {
- using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
- {
- return GetFileSource(extType, model, fileStream);
- }
- }
- }
- return new List<byte>();
- }
- /// <summary>
- /// 获取资源文件文本内容
- /// </summary>
- /// <param name="filePath"></param>
- /// <param name="extType"></param>
- /// <returns></returns>
- public string GetResourceFileStr(string filePath, string extType)
- {
- return Encoding.UTF8.GetString(GetResourceFile(filePath, extType).ToArray());
- }
- /// <summary>
- /// 指定路径得到文件
- /// </summary>
- /// <param name="filePath"></param>
- /// <param name="mineType"></param>
- /// <param name="model"></param>
- /// <returns></returns>
- public List<byte> GetSource(string filePath, string mineType, object model = null)
- {
- var filePathWordLower = filePath.ToLower();
- //如果时内网部署则使用内网的easyEchartLocal.js
- if (IsLocalServer && filePathWordLower.IndexOf("/modules/easyEchart.js", StringComparison.CurrentCultureIgnoreCase) > -1)
- {
- filePath = Regex.Replace(filePath, ".*(/modules/easyEchart[.]js).*", EasyEchartReplace, RegexOptions.IgnoreCase);
- }
- var buffer = GetResourceFile(filePath, mineType, model);
- if (buffer.Count == 0)
- {
- buffer = GetPathFile(filePath, mineType, model);
- }
- return buffer;
- }
- /// <summary>
- /// 替换Echart文件路径
- /// </summary>
- /// <param name="match"></param>
- /// <returns></returns>
- private string EasyEchartReplace(Match match)
- {
- string newJSPath = match.Value;
- if (match.Success && match.Groups.Count > 1)
- {
- newJSPath = match.Value.Replace(match.Groups[1].Value, "/modules/easyEchartLocal.js");
- }
- return newJSPath;
- }
- /// <summary>
- /// 查找资源文件
- /// </summary>
- /// <param name="context"></param>
- /// <returns></returns>
- public bool FindSourceNoModel(HttpListenerContext context)
- {
- bool userCache = true;
- var lastModifiedTime = LastModifiedTime;
- var mineType = "html/text";
- if (context.Request.RawUrl == "/")
- {
- context.Response.Headers.Add("Location", "/index.html");
- context.Response.StatusCode = 302;
- context.Response.Close();
- return true;
- }
- var match = Regex.Match(context.Request.RawUrl, "\\S*[\\.](css|gif|html|json|js|eot|svg|ttf|woff|woff2|jpg|png|ico)");
- if (match.Success && match.Groups.Count > 1)
- {
- //服务器启动版本是否更改
- if (context.Request.Headers["If-Modified-Since"].ToStringEx() == lastModifiedTime.ToUniversalTime().ToString("r"))
- {
- context.Response.StatusCode = 304;
- context.Response.OutputStream.Close();
- return true;
- }
- var buffer = GetSource(match.Value, match.Groups[1].Value, null).ToArray();
- var content = Encoding.UTF8.GetString(buffer);
- if (buffer.Length > 0)
- {
- mineType = MineTypeJsonHelper.GetJsonRoot().GetJPropertyString($"$.{match.Groups[1].Value}");
- if (userCache && match.Groups[0].Value.IndexOf("/index.html", StringComparison.CurrentCultureIgnoreCase) == -1)
- {
- //设置Last-Modified标识最后的文件版本
- context.Response.AddHeader("Last-Modified", lastModifiedTime.ToUniversalTime().ToString("r"));
- //设置缓存超时时间
- context.Response.AddHeader("Cache-Control", "max-age=300");
- }
- //context.Response.ContentEncoding = Encoding.UTF8;
- context.Response.ContentType = mineType + (match.Groups[1].Value == "html" ? ";charset=utf-8" : "");
- if (context.Request.QueryString.Get("IsDownloadType") == "1")
- {
- context.Response.ContentType = "application/octet-stream";
- }
- context.Response.ProtocolVersion = new Version("1.1");
- if (!Regex.IsMatch(context.Request.RawUrl, "\\S*[\\.](gif|eot|svg|ttf|woff|woff2|jpg|png|ico)"))
- {
- ChooseCompress(context, buffer);
- }
- else
- {
- context.Response.ContentLength64 = buffer.Length;
- if (context.Response.OutputStream.CanWrite && context.Request.HttpMethod.ToUpper() != "HEAD")
- {
- context.Response.OutputStream.Write(buffer, 0, buffer.Length);
- }
- else
- {
- Logger.WriteLineWarn($"vcloud disk - http method err, url:{context?.Request?.Url}");
- }
- }
- context.Response.OutputStream.Close();
- buffer = null;
- return true;
- }
- }
- return false;
- }
- private void ChooseCompress(HttpListenerContext context, byte[] data)
- {
- context.Response.AddHeader("Content-Encoding", "deflate");
- CompressDeflate(context, data);
- return;
- }
- private void CompressDeflate(HttpListenerContext context, byte[] data)
- {
- using (MemoryStream memory = new MemoryStream())
- {
- using (var zipStream = new DeflateStream(memory, CompressionMode.Compress, true))
- {
- zipStream.Write(data, 0, data.Length);
- zipStream.Close();
- byte[] buffers = memory.ToArray();
- context.Response.ContentLength64 = buffers.Length;
- if (context.Response.OutputStream.CanWrite && context.Request.HttpMethod.ToUpper() != "HEAD")
- {
- context.Response.OutputStream.Write(buffers, 0, buffers.Length);
- }
- else
- {
- Logger.WriteLineWarn($"vcloud disk - http method err, url:{context?.Request?.Url}");
- }
- }
- }
- }
- }
- }
|