HttpUploadModule.cs
上传用户:whjkdz
上传日期:2013-05-19
资源大小:79k
文件大小:14k
源码类别:

.net编程

开发平台:

C#

  1. #region License
  2. /*
  3. * SunriseUpload - Asp.net Upload Component
  4. *
  5. * Copyright (C) 2004 mic <mic4free@hotmail.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  20. *
  21. * In case your copy of SunriseUpload does not include a copy of the license, you may find it online at 
  22. * http://www.gnu.org/copyleft/gpl.html
  23. *
  24. * You can find new release of this component at http://athena.9966.org/SunriseUpload .
  25. */
  26. #endregion
  27. using System;
  28. using System.Collections;
  29. using System.IO;
  30. using System.Reflection;
  31. using System.Text;
  32. using System.Web;
  33. using System.Xml;
  34. namespace Sunrise.Web.Upload
  35. {
  36. /// <summary>
  37. /// The core of SunriseUpload.
  38. /// </summary>
  39. public class HttpUploadModule : IHttpModule
  40. {
  41. private DateTime beginTime = DateTime.Now;
  42. private HttpUploadModule()
  43. {
  44. }
  45. /// <summary>
  46. /// Get value from preloaded entity body. Identified by name.
  47. /// </summary>
  48. /// <param name="preloadedEntityBody"></param>
  49. /// <param name="name"></param>
  50. /// <returns></returns>
  51. private string AnalysePreloadedEntityBody(byte[] preloadedEntityBody, string name)
  52. {
  53. string val = string.Empty;
  54. string preloadedContent = Utils.GetContext().Request.ContentEncoding.GetString(preloadedEntityBody);
  55. if (preloadedContent.Length > 0)
  56. {
  57. int startIndex = ((preloadedContent.IndexOf(("name="" + name + """)) + 11) + name.Length);
  58. int endIndex = preloadedContent.IndexOf("rn", startIndex);
  59. val = preloadedContent.Substring(startIndex, (endIndex - startIndex));
  60. }
  61. return val;
  62. }
  63. /// <summary>
  64. /// Event handler of request
  65. /// </summary>
  66. /// <param name="sender"></param>
  67. /// <param name="e"></param>
  68. private void Application_BeginRequest(object sender, EventArgs e)
  69. {
  70. HttpApplication application = (sender as HttpApplication);
  71. HttpWorkerRequest workerRequest = GetWorkerRequest();
  72. try
  73. {
  74. //Handle upload request only.
  75. if (!IsUploadRequest(application.Request))
  76. {
  77. return;
  78. }
  79. if (!workerRequest.HasEntityBody())
  80. {
  81. return;
  82. }
  83. //Define a local value to store the current position of total bytes.
  84. int currentPosition = 0;
  85. TimeSpan span = DateTime.Now.Subtract(this.beginTime);
  86. string contentType = application.Context.Request.ContentType.ToLower();
  87. byte[] boundaryData = Encoding.ASCII.GetBytes(("rn--" + contentType.Substring((contentType.IndexOf("boundary=") + 9))).ToCharArray());
  88. int FileLength = Convert.ToInt32(workerRequest.GetKnownRequestHeader(11));
  89. UploadStatus uploadStatus = new UploadStatus();
  90. application.Context.Items.Add("Sunrise_Web_Upload_FileList", new Hashtable());
  91. byte[] preloadedEntityBody = workerRequest.GetPreloadedEntityBody();
  92. currentPosition += preloadedEntityBody.Length;
  93. string uploadGuid = this.AnalysePreloadedEntityBody(preloadedEntityBody, "Sunrise_Web_Upload_UploadGUID");
  94. if (uploadGuid != string.Empty)
  95. {
  96. application.Context.Items.Add("Sunrise_Web_Upload_UploadGUID", uploadGuid);
  97. }
  98. bool isUploadFinished = true;
  99. if ((FileLength > this.GetUpLoadFileLength())
  100. && ((0 > span.TotalHours) || (span.TotalHours > 3)))
  101. {
  102. isUploadFinished = false;
  103. }
  104. if ((0 > span.TotalHours) || (span.TotalHours > 3))
  105. {
  106. isUploadFinished = false;
  107. }
  108. string uploadFolder = this.AnalysePreloadedEntityBody(preloadedEntityBody, "Sunrise_Web_Upload_UploadFolder");
  109. if (uploadFolder.IndexOf(@":") < 0)
  110. {
  111. uploadFolder = Path.GetTempPath();
  112. }
  113. ArrayList readBody = new ArrayList();
  114. RequestStream preloadedStream = new RequestStream(preloadedEntityBody, boundaryData,
  115.                                                   null, RequestStream.FileStatus.Close, RequestStream.ReadStatus.NoRead, uploadFolder, isUploadFinished, application.Context, string.Empty);
  116. readBody.AddRange(preloadedStream.ReadBody);
  117. //Set upload status.
  118. if (uploadGuid != string.Empty)
  119. {
  120. uploadStatus.FileLength = FileLength;
  121. uploadStatus.ReceivedLength = currentPosition;
  122. uploadStatus.FileName = preloadedStream.OriginalFileName;
  123. uploadStatus.FileCount = ((Hashtable) application.Context.Items["Sunrise_Web_Upload_FileList"]).Count;
  124. application.Application[("_UploadGUID_" + uploadGuid)] = uploadStatus;
  125. }
  126. //Is all data have been preload?
  127. if (!workerRequest.IsEntireEntityBodyIsPreloaded())
  128. {
  129. byte[] boudaryContent;
  130. ArrayList contentBody;
  131. //Define size of boundary.
  132. int boundarySize = 204800;
  133. byte[] boudaryBuffer = new byte[boundarySize];
  134. //Read each data block into read body array.
  135. while (((FileLength - currentPosition) >= boundarySize))
  136. {
  137. //If client is disconnected, clear all resources in use.
  138. if (!application.Context.Response.IsClientConnected)
  139. {
  140. this.ReleaseRes(application);
  141. }
  142. //Read bytes from request.
  143. boundarySize = workerRequest.ReadEntityBody(boudaryBuffer, boudaryBuffer.Length);
  144. currentPosition += boundarySize;
  145. contentBody = preloadedStream.ContentBody;
  146. if (contentBody.Count > 0)
  147. {
  148. boudaryContent = new byte[(contentBody.Count + boudaryBuffer.Length)];
  149. contentBody.CopyTo(boudaryContent, 0);
  150. boudaryBuffer.CopyTo(boudaryContent, contentBody.Count);
  151. preloadedStream = new RequestStream(boudaryContent, boundaryData,
  152.                                     preloadedStream.FileStream, preloadedStream.FStatus, preloadedStream.RStatus, uploadFolder, isUploadFinished, application.Context, preloadedStream.OriginalFileName);
  153. }
  154. else
  155. {
  156. preloadedStream = new RequestStream(boudaryBuffer, boundaryData,
  157.                                     preloadedStream.FileStream, preloadedStream.FStatus, preloadedStream.RStatus, uploadFolder, isUploadFinished, application.Context, preloadedStream.OriginalFileName);
  158. }
  159. //Append data block to read body array
  160. readBody.AddRange(preloadedStream.ReadBody);
  161. //Set upload status.
  162. if (uploadGuid != string.Empty)
  163. {
  164. uploadStatus.ReceivedLength = currentPosition;
  165. uploadStatus.FileName = preloadedStream.OriginalFileName;
  166. uploadStatus.FileCount = ((Hashtable) application.Context.Items["Sunrise_Web_Upload_FileList"]).Count;
  167. application.Application[("_UploadGUID_" + uploadGuid)] = uploadStatus;
  168. }
  169. }
  170. //The rest request data
  171. boudaryBuffer = new byte[FileLength - currentPosition];
  172. if (!application.Context.Response.IsClientConnected
  173. && (preloadedStream.FStatus == RequestStream.FileStatus.Open))
  174. {
  175. this.ReleaseRes(application);
  176. }
  177. //Size of spare request data.
  178. boundarySize = workerRequest.ReadEntityBody(boudaryBuffer, boudaryBuffer.Length);
  179. contentBody = preloadedStream.ContentBody;
  180. if (contentBody.Count > 0)
  181. {
  182. boudaryContent = new byte[(contentBody.Count + boudaryBuffer.Length)];
  183. contentBody.CopyTo(boudaryContent, 0);
  184. boudaryBuffer.CopyTo(boudaryContent, contentBody.Count);
  185. preloadedStream = new RequestStream(boudaryContent, boundaryData, preloadedStream.FileStream, preloadedStream.FStatus, preloadedStream.RStatus, uploadFolder, isUploadFinished, application.Context, preloadedStream.OriginalFileName);
  186. }
  187. else
  188. {
  189. preloadedStream = new RequestStream(boudaryBuffer, boundaryData, preloadedStream.FileStream, preloadedStream.FStatus, preloadedStream.RStatus, uploadFolder, isUploadFinished, application.Context, preloadedStream.OriginalFileName);
  190. }
  191. //Append the rest data block to read body array.
  192. readBody.AddRange(preloadedStream.ReadBody);
  193. if (uploadGuid != string.Empty)
  194. {
  195. uploadStatus.ReceivedLength = (currentPosition + boudaryBuffer.Length);
  196. uploadStatus.FileName = preloadedStream.OriginalFileName;
  197. uploadStatus.FileCount = ((Hashtable) application.Context.Items["Sunrise_Web_Upload_FileList"]).Count;
  198. if (isUploadFinished)
  199. {
  200. uploadStatus.State = UploadState.Uploaded;
  201. }
  202. else
  203. {
  204. application.Application.Remove(("_UploadGUID_" + uploadGuid));
  205. }
  206. }
  207. }
  208. //Copy all data to byte buffer.
  209. byte[] readedBodyBuffer = new byte[readBody.Count];
  210. readBody.CopyTo(readedBodyBuffer);
  211. this.InjectTextParts(workerRequest, readedBodyBuffer);
  212. ClearApplication(application);
  213. }
  214. catch (Exception exception)
  215. {
  216. //If exception has been throw, clear all resources in use.
  217. this.ReleaseRes(application);
  218. throw exception;
  219. }
  220. }
  221. private HttpWorkerRequest GetWorkerRequest()
  222. {
  223. IServiceProvider provider = HttpContext.Current;
  224. return ((HttpWorkerRequest) provider.GetService(typeof (HttpWorkerRequest)));
  225. }
  226. private bool IsUploadRequest(HttpRequest request)
  227. {
  228. return request.ContentType.ToLower().StartsWith("multipart/form-data");
  229. }
  230. /// <summary>
  231. /// Even handler of end request.
  232. /// </summary>
  233. /// <param name="sender"></param>
  234. /// <param name="e"></param>
  235. private void Application_EndRequest(object sender, EventArgs e)
  236. {
  237. HttpApplication application = (sender as HttpApplication);
  238. application.Context.Items.Clear();
  239. }
  240. /// <summary>
  241. /// 
  242. /// </summary>
  243. /// <param name="sender"></param>
  244. /// <param name="e"></param>
  245. private void Application_Error(object sender, EventArgs e)
  246. {
  247. HttpApplication application = (sender as HttpApplication);
  248. this.ReleaseRes(application);
  249. }
  250. /// <summary>
  251. /// Clear all context items, delete temporary file.
  252. /// </summary>
  253. /// <param name="application"></param>
  254. private void ReleaseRes(HttpApplication application)
  255. {
  256. ClearApplication(application);
  257. if (application.Context.Items["Sunrise_Web_Upload_FileList"] != null)
  258. {
  259. Hashtable fileList = ((Hashtable) application.Context.Items["Sunrise_Web_Upload_FileList"]);
  260. foreach (object obj in fileList.Values)
  261. {
  262. if (!File.Exists(obj.ToString()))
  263. {
  264. continue;
  265. }
  266. File.Delete(obj.ToString());
  267. }
  268. }
  269. application.Context.Items.Clear();
  270. }
  271. private void ClearApplication(HttpApplication application)
  272. {
  273. if ((application.Context.Items["Sunrise_Web_Upload_FileStatus"] != null)
  274. && (((byte) ((RequestStream.FileStatus) application.Context.Items["Sunrise_Web_Upload_FileStatus"])) == 0))
  275. {
  276. FileStream fileStream = ((FileStream) application.Context.Items["Sunrise_Web_Upload_FileStream"]);
  277. fileStream.Close();
  278. }
  279. if (application.Context.Items["Sunrise_Web_Upload_UploadGUID"] != null)
  280. {
  281. string uploadGuid = ((string) application.Context.Items["Sunrise_Web_Upload_UploadGUID"]);
  282. application.Application.Remove(("_UploadGUID_" + uploadGuid));
  283. }
  284. }
  285. public void Dispose()
  286. {
  287. }
  288. /// <summary>
  289. /// 
  290. /// </summary>
  291. /// <param name="application"></param>
  292. public void Init(HttpApplication application)
  293. {
  294. application.BeginRequest += new EventHandler(this.Application_BeginRequest);
  295. application.EndRequest += new EventHandler(this.Application_EndRequest);
  296. application.Error += new EventHandler(this.Application_Error);
  297. }
  298. /// <summary>
  299. /// 
  300. /// </summary>
  301. /// <param name="request"></param>
  302. /// <param name="textParts"></param>
  303. /// <returns></returns>
  304. private byte[] InjectTextParts(HttpWorkerRequest request, byte[] textParts)
  305. {
  306. Type type;
  307. BindingFlags flags = (BindingFlags.NonPublic | BindingFlags.Instance);
  308. //Is there application host IIS6.0?
  309. if (Utils.GetContext().Request.ServerVariables["SERVER_SOFTWARE"].Equals("Microsoft-IIS/6.0"))
  310. {
  311. type = request.GetType().BaseType.BaseType;
  312. }
  313. else
  314. {
  315. type = request.GetType().BaseType;
  316. }
  317. int dataLength = textParts.Length;
  318. //Set values of working request
  319. type.GetField("_contentAvailLength", flags).SetValue(request, dataLength);
  320. type.GetField("_contentTotalLength", flags).SetValue(request, dataLength);
  321. type.GetField("_preloadedContent", flags).SetValue(request, textParts);
  322. type.GetField("_preloadedContentRead", flags).SetValue(request, true);
  323. return textParts;
  324. }
  325. /// <summary>
  326. /// Get value of "maxRequestLength" setting.
  327. /// </summary>
  328. /// <returns>
  329. /// If defined maxRequestLength setting in web.config
  330. /// and it value small then the one which defined in mechine.config, get it.
  331. /// Otherwise get it from mechine.config.
  332. /// </returns>
  333. private double GetUpLoadFileLength()
  334. {
  335. string assemblyLocation = typeof (string).Assembly.Location;
  336. assemblyLocation = Path.GetDirectoryName(assemblyLocation);
  337. assemblyLocation = Path.Combine(assemblyLocation, @"CONFIGmachine.config");
  338. XmlDocument xmlDocument = new XmlDocument();
  339. //Load mechine.config
  340. xmlDocument.Load(assemblyLocation);
  341. double maxRequestLength = Convert.ToDouble(xmlDocument.SelectSingleNode("configuration/system.web/httpRuntime/@maxRequestLength").Value);
  342. //Load web.config.
  343. xmlDocument.Load(Path.Combine(Utils.GetContext().Request.PhysicalApplicationPath, "web.config"));
  344. XmlNode node = xmlDocument.SelectSingleNode("configuration/system.web/httpRuntime/@maxRequestLength");
  345. if (node != null)
  346. {
  347. double length = Convert.ToDouble(node.Value);
  348. if (length < maxRequestLength)
  349. {
  350. maxRequestLength = length;
  351. }
  352. }
  353. //Release xml document object.
  354. xmlDocument = null;
  355. return (maxRequestLength*1024);
  356. }
  357. }
  358. }