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.

727 lines
26 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. #if NETFX
  2. using Apewer;
  3. using Apewer.Internals;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Collections.Specialized;
  7. using System.Text;
  8. using System.Web;
  9. using System.Web.Configuration;
  10. namespace Apewer.Web
  11. {
  12. /// <summary>实现页面的常用功能。</summary>
  13. public class PageUtility // : System.Web.UI.Page
  14. {
  15. #region Property
  16. /// <summary>获取客户端 IP 地址。</summary>
  17. public static string ClientIP
  18. {
  19. get
  20. {
  21. var ip1 = Variable("http_x_forwarded_for");
  22. var ip2 = Variable("remote_addr");
  23. var e1 = string.IsNullOrEmpty(ip1);
  24. var e2 = string.IsNullOrEmpty(ip2);
  25. var result = TextUtility.Empty;
  26. if (e1)
  27. {
  28. if (e2) result = TextUtility.Empty;
  29. else result = TextUtility.Merge(ip2);
  30. }
  31. else
  32. {
  33. if (e2) result = TextUtility.Merge(ip1);
  34. else result = TextUtility.Merge(ip1, ",", ip2);
  35. }
  36. return result;
  37. }
  38. }
  39. /// <summary>检查客户端是否在线。</summary>
  40. public static bool Connected
  41. {
  42. get
  43. {
  44. try { return HttpContext.Current.Response.IsClientConnected; }
  45. catch { return false; }
  46. }
  47. }
  48. /// <summary>获取服务器执行的文件 URL。</summary>
  49. public static string ExecutingUrl
  50. {
  51. get
  52. {
  53. return Variable("url");
  54. }
  55. }
  56. /// <summary>获取上一次的 URL。</summary>
  57. public static string PreviousUrl
  58. {
  59. get
  60. {
  61. return Variable("http_referer");
  62. }
  63. }
  64. /// <summary>获取客户端请求的 URL。</summary>
  65. public static string RequestingUrl
  66. {
  67. get
  68. {
  69. try { return HttpContext.Current.Request.Url.OriginalString; }
  70. catch { return TextUtility.Empty; }
  71. }
  72. }
  73. /// <summary>获取分段的 URL。</summary>
  74. public static string[] SegmentalUrl
  75. {
  76. get
  77. {
  78. try { return HttpContext.Current.Request.Url.AbsolutePath.Split('/'); }
  79. catch { return new string[0]; }
  80. }
  81. }
  82. /// <summary>获取浏览器用户代理。</summary>
  83. public static string UserAgent
  84. {
  85. get
  86. {
  87. return Variable("http_user_agent");
  88. }
  89. }
  90. /// <summary>获取服务器变量。</summary>
  91. public static Dictionary<string, string> Variables
  92. {
  93. get
  94. {
  95. var collection = HttpContext.Current.Request.ServerVariables;
  96. var dictionary = new Dictionary<string, string>();
  97. foreach (var key in collection.AllKeys)
  98. {
  99. if (dictionary.ContainsKey(key)) continue;
  100. dictionary.Add(key, collection[key] ?? "");
  101. }
  102. return dictionary;
  103. }
  104. }
  105. #endregion
  106. #region server / web.config
  107. /// <summary>获取访问 web.config 文件中 configuration.appSettings 子项的集合。</summary>
  108. public static NameValueCollection AppSettings { get { return WebConfigurationManager.AppSettings; } }
  109. /// <summary>获取从 web.config 文件中 configuration.appSettings 的子项。</summary>
  110. public static Dictionary<string, string> GetAppSettings()
  111. {
  112. var ts = new TextSet(true);
  113. try
  114. {
  115. var appsettings = WebConfigurationManager.AppSettings;
  116. foreach (var key in appsettings.AllKeys)
  117. {
  118. var value = appsettings[key];
  119. ts[key] = value;
  120. }
  121. }
  122. catch { }
  123. return ts.Origin();
  124. }
  125. /// <summary>获取从 web.config 文件中 configuration.appSettings 的子项。</summary>
  126. public static string GetAppSettings(string key)
  127. {
  128. if (key != null)
  129. {
  130. try
  131. {
  132. var appsettings = WebConfigurationManager.AppSettings;
  133. var value = appsettings[key];
  134. return TextUtility.Trim(value);
  135. }
  136. catch { }
  137. }
  138. return "";
  139. }
  140. /// <summary>设置 web.config 文件中 configuration.appSettings 的子项。</summary>
  141. public static bool SetAppSettings(string key, string value)
  142. {
  143. try
  144. {
  145. WebConfigurationManager.AppSettings.Set(key ?? "", value ?? "");
  146. return true;
  147. }
  148. catch { return false; }
  149. }
  150. /// <summary>获取服务器变量。</summary>
  151. public static string Variable(string name)
  152. {
  153. var result = "";
  154. if (!string.IsNullOrEmpty(name))
  155. {
  156. string vname = name.ToLower();
  157. try { result = HttpContext.Current.Request.ServerVariables[vname]; }
  158. finally { }
  159. }
  160. return result ?? "";
  161. }
  162. /// <summary>执行 ASPX 文件,执行完毕后返回原程序继续执行。</summary>
  163. public static bool Execute(string url)
  164. {
  165. try { HttpContext.Current.Server.Execute(url); return true; }
  166. catch { return false; }
  167. }
  168. /// <summary>执行 ASPX 文件,不再返回。</summary>
  169. public static bool Transfer(string url)
  170. {
  171. try { HttpContext.Current.Server.Transfer(url); return true; }
  172. catch { return false; }
  173. }
  174. #endregion
  175. #region cookie / session
  176. /// <summary>获取 Cookie 值。</summary>
  177. public static string GetCookie(string name)
  178. {
  179. if (!string.IsNullOrEmpty(name))
  180. {
  181. try
  182. {
  183. return HttpContext.Current.Request.Cookies[name].Value;
  184. }
  185. finally { }
  186. }
  187. return "";
  188. }
  189. /// <summary>清除所有 Cookie。</summary>
  190. public static void ClearCookie()
  191. {
  192. try
  193. {
  194. HttpContext.Current.Response.Cookies.Clear();
  195. }
  196. finally { }
  197. }
  198. /// <summary>获取会话变量值。</summary>
  199. public static string GetSession(string name)
  200. {
  201. if (!string.IsNullOrEmpty(name))
  202. {
  203. try
  204. {
  205. object session = HttpContext.Current.Session[name];
  206. if (session != null) return session.ToString();
  207. }
  208. finally { }
  209. }
  210. return "";
  211. }
  212. #endregion
  213. #region request
  214. /// <summary>获取 POST 提交的数据。</summary>
  215. public static byte[] GetPost()
  216. {
  217. try
  218. {
  219. var length = HttpContext.Current.Request.InputStream.Length;
  220. if (length > 0)
  221. {
  222. var data = new byte[(int)length];
  223. HttpContext.Current.Request.InputStream.Read(data, 0, (int)length);
  224. return data;
  225. }
  226. }
  227. finally { }
  228. return BytesUtility.Empty;
  229. }
  230. /// <summary>获取物理路径。</summary>
  231. public static string MapPath(string url)
  232. {
  233. try
  234. {
  235. return HttpContext.Current.Server.MapPath(url);
  236. }
  237. catch { return ""; }
  238. }
  239. /// <summary>获取 GET 提交的值。</summary>
  240. public static string QueryString(string name, bool decode = false)
  241. {
  242. if (string.IsNullOrEmpty(name)) return "";
  243. try
  244. {
  245. var value = HttpContext.Current.Request.QueryString[name] ?? "";
  246. if (decode) value = HttpUtility.UrlDecode(value);
  247. return value;
  248. }
  249. catch { }
  250. return "";
  251. }
  252. /// <summary>重定向到新 URL。</summary>
  253. public static void Redirect(string url)
  254. {
  255. try
  256. {
  257. HttpContext.Current.Response.Redirect(string.IsNullOrEmpty(url) ? "/" : url);
  258. }
  259. catch { }
  260. }
  261. /// <summary>移除 Cookie。</summary>
  262. public static bool RemoveCookie(string name)
  263. {
  264. if (!string.IsNullOrEmpty(name))
  265. {
  266. try
  267. {
  268. HttpContext.Current.Response.Cookies.Remove(name);
  269. return true;
  270. }
  271. finally { }
  272. }
  273. return false;
  274. }
  275. /// <summary>获取 FORM 提交的文件。</summary>
  276. public static Dictionary<string, byte[]> RequestFile()
  277. {
  278. var result = new Dictionary<string, byte[]>();
  279. try
  280. {
  281. var context = HttpContext.Current;
  282. if (context == null) return result;
  283. foreach (var key in context.Request.Files.AllKeys)
  284. {
  285. var file = context.Request.Files.Get(key);
  286. var exist = result.ContainsKey(file.FileName);
  287. if (exist) continue;
  288. var memory = new System.IO.MemoryStream();
  289. var read = BytesUtility.Read(file.InputStream, memory);
  290. var data = memory.ToArray();
  291. memory.Dispose();
  292. if (data.Length == file.ContentLength)
  293. {
  294. result.Add(file.FileName, data);
  295. }
  296. }
  297. }
  298. catch { }
  299. return result;
  300. }
  301. /// <summary>获取 POST 提交的值。</summary>
  302. public static string RequestForm(string name)
  303. {
  304. try
  305. {
  306. if (!string.IsNullOrEmpty(name)) return HttpContext.Current.Request.Form[name];
  307. }
  308. finally { }
  309. return "";
  310. }
  311. /// <summary>设置 Cookie 值。</summary>
  312. public static bool SetCookie(string name, string value)
  313. {
  314. if (!string.IsNullOrEmpty(name))
  315. {
  316. try
  317. {
  318. HttpContext.Current.Response.Cookies[name].Value = value;
  319. return true;
  320. }
  321. finally { }
  322. }
  323. return false;
  324. }
  325. /// <summary>设置 Cookie 过期时间。</summary>
  326. public static bool SetCookie(string name, DateTime expires)
  327. {
  328. if (!string.IsNullOrEmpty(name) && expires != null)
  329. {
  330. try
  331. {
  332. HttpContext.Current.Response.Cookies[name].Expires = expires;
  333. return true;
  334. }
  335. finally { }
  336. }
  337. return false;
  338. }
  339. /// <summary>设置会话变量值。</summary>
  340. public static bool SetSession(string name, string value)
  341. {
  342. if (!string.IsNullOrEmpty(name))
  343. {
  344. try
  345. {
  346. if (string.IsNullOrEmpty(value))
  347. {
  348. HttpContext.Current.Session.Remove(value);
  349. }
  350. else
  351. {
  352. HttpContext.Current.Session[name] = value;
  353. }
  354. return true;
  355. }
  356. finally { }
  357. }
  358. return false;
  359. }
  360. #endregion
  361. #region response
  362. /// <summary>设置响应:启用输出缓冲,禁用缓存,设置字符集为“UTF-8”。</summary>
  363. public static void InitializeResponse()
  364. {
  365. try
  366. {
  367. HttpContext.Current.Response.Buffer = true;
  368. HttpContext.Current.Response.Expires = 0;
  369. HttpContext.Current.Response.Charset = "utf-8";
  370. }
  371. finally { }
  372. }
  373. /// <summary>清空缓冲区内容,默认不向客户端发送缓冲区内容。</summary>
  374. public void ClearResponse()
  375. {
  376. try { HttpContext.Current.Response.Clear(); } catch { }
  377. }
  378. /// <summary>清空缓冲区内容,可选是否向客户端发送缓冲区内容。</summary>
  379. public void ClearResponse(bool flush)
  380. {
  381. try { if (flush) HttpContext.Current.Response.Flush(); } catch { }
  382. try { HttpContext.Current.Response.Clear(); } catch { }
  383. }
  384. /// <summary>向客户端发送缓冲区内容,并结束页面的执行。</summary>
  385. public static void StopResponse()
  386. {
  387. try { HttpContext.Current.Response.Flush(); } finally { }
  388. try { HttpContext.Current.Response.Close(); } finally { }
  389. }
  390. /// <summary>停止并关闭响应流。可指定向发送缓冲区的数据。</summary>
  391. public static void StopResponse(bool flush)
  392. {
  393. try { if (flush) HttpContext.Current.Response.Flush(); } finally { }
  394. try { HttpContext.Current.Response.Close(); } finally { }
  395. // try { HttpContext.Current.Response.End(); } finally { }
  396. }
  397. /// <summary>向响应流写入文本。</summary>
  398. public static Exception Write(params string[] text)
  399. {
  400. if (text == null) return null;
  401. foreach (var i in text)
  402. {
  403. if (string.IsNullOrEmpty(i)) continue;
  404. try
  405. {
  406. HttpContext.Current.Response.Write(i);
  407. }
  408. catch (Exception exception) { return exception; }
  409. }
  410. return null;
  411. }
  412. /// <summary>输出二进制。Content-Type 为“application/octet-stream”。</summary>
  413. public static Exception Write(byte[] bytes)
  414. {
  415. var ct = "application/octet-stream";
  416. var data = bytes ?? BytesUtility.Empty;
  417. try
  418. {
  419. HttpContext.Current.Response.ContentType = ct;
  420. HttpContext.Current.Response.OutputStream.Write(bytes, 0, bytes.Length);
  421. return null;
  422. }
  423. catch (Exception exception) { return exception; }
  424. }
  425. /// <summary>输出二进制。Content-Type 默认为“application/octet-stream”。</summary>
  426. public static Exception Write(byte[] bytes, string contentType)
  427. {
  428. var data = bytes ?? BytesUtility.Empty;
  429. var contenttype = TextUtility.IsBlank(contentType) ? "application/octet-stream" : contentType;
  430. try
  431. {
  432. HttpContext.Current.Response.ContentType = contenttype;
  433. if (data.LongLength > 0L) HttpContext.Current.Response.OutputStream.Write(data, 0, data.Length);
  434. return null;
  435. }
  436. catch (Exception exception) { return exception; }
  437. }
  438. /// <summary>输出文件。</summary>
  439. public static Exception WriteFile(string name, string path)
  440. {
  441. var vname = StorageUtility.FixFileName(name);
  442. try
  443. {
  444. HttpContext.Current.Response.ContentType = "application/octet-stream";
  445. if (!TextUtility.IsBlank(vname))
  446. {
  447. HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(vname, Encoding.UTF8));
  448. }
  449. HttpContext.Current.Response.WriteFile(path, false);
  450. HttpContext.Current.Response.Flush();
  451. HttpContext.Current.Response.End();
  452. return null;
  453. }
  454. catch (Exception exception) { return exception; }
  455. }
  456. /// <summary>输出文件。Content-Type 值为“application/octet-stream”。</summary>
  457. public static Exception WriteFile(string name, params byte[] bytes)
  458. {
  459. var vname = StorageUtility.FixFileName(name);
  460. try
  461. {
  462. HttpContext.Current.Response.ContentType = "application/octet-stream";
  463. if (!TextUtility.IsBlank(vname))
  464. {
  465. HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode(vname, Encoding.UTF8));
  466. }
  467. HttpContext.Current.Response.OutputStream.Write(bytes, 0, bytes.Length);
  468. return null;
  469. }
  470. catch (Exception exception) { return exception; }
  471. }
  472. /// <summary>编码 URL。</summary>
  473. public static string UrlEncode(string text)
  474. {
  475. try { return HttpUtility.UrlEncode(text); }
  476. catch { return TextUtility.Empty; }
  477. }
  478. /// <summary>解码 URL。</summary>
  479. public static string UrlDecode(string text)
  480. {
  481. try { return HttpUtility.UrlDecode(text); }
  482. catch { return TextUtility.Empty; }
  483. }
  484. /// <summary></summary>
  485. public static string GetMime(string name)
  486. {
  487. var octetstream = "application/octet-stream";
  488. if (string.IsNullOrEmpty(name)) return octetstream;
  489. if (!name.Contains(".")) return octetstream;
  490. var array = name.ToLower().Split('.');
  491. var extension = array[array.Length - 1];
  492. var mime = null as string;
  493. if (string.IsNullOrEmpty(mime)) mime = GetMime_Nginx_1_16_1(extension);
  494. return string.IsNullOrEmpty(mime) ? octetstream : mime;
  495. }
  496. private static TextSet GetMime_Customized()
  497. {
  498. var ts = new TextSet(true);
  499. ts[""] = "application/octet-stream";
  500. // 纯文本文件。
  501. ts["htm"] = "text/html";
  502. ts["html"] = "text/html";
  503. ts["css"] = "text/css";
  504. ts["js"] = "application/x-javascript";
  505. ts["txt"] = "text/plain";
  506. ts["txt"] = "text/plain";
  507. // 字体文件。
  508. ts["eot"] = "application/vnd.ms-fontobject";
  509. ts["ttf"] = "application/x-font-ttf";
  510. ts["woff"] = "application/x-font-woff";
  511. // 图像文件。
  512. ts["bmp"] = "image/bmp";
  513. ts["gif"] = "image/gif";
  514. ts["ico"] = "imaeg/x-icon";
  515. ts["jpg"] = "image/jpg";
  516. ts["png"] = "image/png";
  517. ts["svg"] = "image/svg+xml";
  518. // 音视频文件。
  519. ts["avi"] = "video/avi";
  520. ts["mov"] = "video/mov";
  521. ts["mp3"] = "audio/mp3";
  522. ts["mp4"] = "video/mp4";
  523. ts["ogg"] = "video/ogg";
  524. ts["rm"] = "video/rm";
  525. ts["rmvb"] = "video/rmvb";
  526. ts["wav"] = "audio/wav";
  527. ts["webm"] = "video/webm";
  528. ts["wma"] = "video/wma";
  529. ts["wmv"] = "video/wmv";
  530. // 常用二进制文件。
  531. //ts["7z"] = "application/octet-stream";
  532. //ts["exe"] = "application/octet-stream";
  533. //ts["gz"] = "application/octet-stream";
  534. //ts["rar"] = "application/octet-stream";
  535. //ts["tar"] = "application/octet-stream";
  536. //ts["zip"] = "application/x-zip-compressed";
  537. return ts;
  538. }
  539. private static string GetMime_Nginx_1_16_1(string extension)
  540. {
  541. switch (extension)
  542. {
  543. case "3gp": return "video/3gpp";
  544. case "3gpp": return "video/3gpp";
  545. case "7z": return "application/x-7z-compressed";
  546. case "ai": return "application/postscript";
  547. case "asf": return "video/x-ms-asf";
  548. case "asx": return "video/x-ms-asf";
  549. case "atom": return "application/atom+xml";
  550. case "avi": return "video/x-msvideo";
  551. case "bin": return "application/octet-stream";
  552. case "bmp": return "image/x-ms-bmp";
  553. case "cco": return "application/x-cocoa";
  554. case "crt": return "application/x-x509-ca-cert";
  555. case "css": return "text/css";
  556. case "deb": return "application/octet-stream";
  557. case "der": return "application/x-x509-ca-cert";
  558. case "dll": return "application/octet-stream";
  559. case "dmg": return "application/octet-stream";
  560. case "doc": return "application/msword";
  561. case "docx": return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
  562. case "ear": return "application/java-archive";
  563. case "eot": return "application/vnd.ms-fontobject";
  564. case "eps": return "application/postscript";
  565. case "exe": return "application/octet-stream";
  566. case "flv": return "video/x-flv";
  567. case "gif": return "image/gif";
  568. case "hqx": return "application/mac-binhex40";
  569. case "htc": return "text/x-component";
  570. case "htm": return "text/html";
  571. case "html": return "text/html";
  572. case "ico": return "image/x-icon";
  573. case "img": return "application/octet-stream";
  574. case "iso": return "application/octet-stream";
  575. case "jad": return "text/vnd.sun.j2me.app-descriptor";
  576. case "jar": return "application/java-archive";
  577. case "jardiff": return "application/x-java-archive-diff";
  578. case "jng": return "image/x-jng";
  579. case "jnlp": return "application/x-java-jnlp-file";
  580. case "jpeg": return "image/jpeg";
  581. case "jpg": return "image/jpeg";
  582. case "js": return "application/javascript";
  583. case "json": return "application/json";
  584. case "kar": return "audio/midi";
  585. case "kml": return "application/vnd.google-earth.kml+xml";
  586. case "kmz": return "application/vnd.google-earth.kmz";
  587. case "m3u8": return "application/vnd.apple.mpegurl";
  588. case "m4a": return "audio/x-m4a";
  589. case "m4v": return "video/x-m4v";
  590. case "mid": return "audio/midi";
  591. case "midi": return "audio/midi";
  592. case "mml": return "text/mathml";
  593. case "mng": return "video/x-mng";
  594. case "mov": return "video/quicktime";
  595. case "mp3": return "audio/mpeg";
  596. case "mp4": return "video/mp4";
  597. case "mpeg": return "video/mpeg";
  598. case "mpg": return "video/mpeg";
  599. case "msi": return "application/octet-stream";
  600. case "msm": return "application/octet-stream";
  601. case "msp": return "application/octet-stream";
  602. case "odg": return "application/vnd.oasis.opendocument.graphics";
  603. case "odp": return "application/vnd.oasis.opendocument.presentation";
  604. case "ods": return "application/vnd.oasis.opendocument.spreadsheet";
  605. case "odt": return "application/vnd.oasis.opendocument.text";
  606. case "ogg": return "audio/ogg";
  607. case "pdb": return "application/x-pilot";
  608. case "pdf": return "application/pdf";
  609. case "pem": return "application/x-x509-ca-cert";
  610. case "pl": return "application/x-perl";
  611. case "pm": return "application/x-perl";
  612. case "png": return "image/png";
  613. case "ppt": return "application/vnd.ms-powerpoint";
  614. case "pptx": return "application/vnd.openxmlformats-officedocument.presentationml.presentation";
  615. case "prc": return "application/x-pilot";
  616. case "ps": return "application/postscript";
  617. case "ra": return "audio/x-realaudio";
  618. case "rar": return "application/x-rar-compressed";
  619. case "rpm": return "application/x-redhat-package-manager";
  620. case "rss": return "application/rss+xml";
  621. case "rtf": return "application/rtf";
  622. case "run": return "application/x-makeself";
  623. case "sea": return "application/x-sea";
  624. case "shtml": return "text/html";
  625. case "sit": return "application/x-stuffit";
  626. case "svg": return "image/svg+xml";
  627. case "svgz": return "image/svg+xml";
  628. case "swf": return "application/x-shockwave-flash";
  629. case "tcl": return "application/x-tcl";
  630. case "tif": return "image/tiff";
  631. case "tiff": return "image/tiff";
  632. case "tk": return "application/x-tcl";
  633. case "ts": return "video/mp2t";
  634. case "txt": return "text/plain";
  635. case "war": return "application/java-archive";
  636. case "wbmp": return "image/vnd.wap.wbmp";
  637. case "webm": return "video/webm";
  638. case "webp": return "image/webp";
  639. case "wml": return "text/vnd.wap.wml";
  640. case "wmlc": return "application/vnd.wap.wmlc";
  641. case "wmv": return "video/x-ms-wmv";
  642. case "woff": return "font/woff";
  643. case "woff2": return "font/woff2";
  644. case "xhtml": return "application/xhtml+xml";
  645. case "xls": return "application/vnd.ms-excel";
  646. case "xlsx": return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
  647. case "xml": return "text/xml";
  648. case "xpi": return "application/x-xpinstall";
  649. case "xspf": return "application/xspf+xml";
  650. case "zip": return "application/zip";
  651. }
  652. return null;
  653. }
  654. #endregion
  655. }
  656. }
  657. #endif