HttpUploadModule.cs
上传用户:whjkdz
上传日期:2013-05-19
资源大小:79k
文件大小:14k
- #region License
- /*
- * SunriseUpload - Asp.net Upload Component
- *
- * Copyright (C) 2004 mic <mic4free@hotmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * In case your copy of SunriseUpload does not include a copy of the license, you may find it online at
- * http://www.gnu.org/copyleft/gpl.html
- *
- * You can find new release of this component at http://athena.9966.org/SunriseUpload .
- */
- #endregion
- using System;
- using System.Collections;
- using System.IO;
- using System.Reflection;
- using System.Text;
- using System.Web;
- using System.Xml;
- namespace Sunrise.Web.Upload
- {
- /// <summary>
- /// The core of SunriseUpload.
- /// </summary>
- public class HttpUploadModule : IHttpModule
- {
- private DateTime beginTime = DateTime.Now;
- private HttpUploadModule()
- {
- }
- /// <summary>
- /// Get value from preloaded entity body. Identified by name.
- /// </summary>
- /// <param name="preloadedEntityBody"></param>
- /// <param name="name"></param>
- /// <returns></returns>
- private string AnalysePreloadedEntityBody(byte[] preloadedEntityBody, string name)
- {
- string val = string.Empty;
- string preloadedContent = Utils.GetContext().Request.ContentEncoding.GetString(preloadedEntityBody);
- if (preloadedContent.Length > 0)
- {
- int startIndex = ((preloadedContent.IndexOf(("name="" + name + """)) + 11) + name.Length);
- int endIndex = preloadedContent.IndexOf("rn", startIndex);
- val = preloadedContent.Substring(startIndex, (endIndex - startIndex));
- }
- return val;
- }
- /// <summary>
- /// Event handler of request
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void Application_BeginRequest(object sender, EventArgs e)
- {
- HttpApplication application = (sender as HttpApplication);
- HttpWorkerRequest workerRequest = GetWorkerRequest();
- try
- {
- //Handle upload request only.
- if (!IsUploadRequest(application.Request))
- {
- return;
- }
- if (!workerRequest.HasEntityBody())
- {
- return;
- }
- //Define a local value to store the current position of total bytes.
- int currentPosition = 0;
- TimeSpan span = DateTime.Now.Subtract(this.beginTime);
- string contentType = application.Context.Request.ContentType.ToLower();
- byte[] boundaryData = Encoding.ASCII.GetBytes(("rn--" + contentType.Substring((contentType.IndexOf("boundary=") + 9))).ToCharArray());
- int FileLength = Convert.ToInt32(workerRequest.GetKnownRequestHeader(11));
- UploadStatus uploadStatus = new UploadStatus();
- application.Context.Items.Add("Sunrise_Web_Upload_FileList", new Hashtable());
- byte[] preloadedEntityBody = workerRequest.GetPreloadedEntityBody();
- currentPosition += preloadedEntityBody.Length;
- string uploadGuid = this.AnalysePreloadedEntityBody(preloadedEntityBody, "Sunrise_Web_Upload_UploadGUID");
- if (uploadGuid != string.Empty)
- {
- application.Context.Items.Add("Sunrise_Web_Upload_UploadGUID", uploadGuid);
- }
- bool isUploadFinished = true;
- if ((FileLength > this.GetUpLoadFileLength())
- && ((0 > span.TotalHours) || (span.TotalHours > 3)))
- {
- isUploadFinished = false;
- }
- if ((0 > span.TotalHours) || (span.TotalHours > 3))
- {
- isUploadFinished = false;
- }
- string uploadFolder = this.AnalysePreloadedEntityBody(preloadedEntityBody, "Sunrise_Web_Upload_UploadFolder");
- if (uploadFolder.IndexOf(@":") < 0)
- {
- uploadFolder = Path.GetTempPath();
- }
- ArrayList readBody = new ArrayList();
- RequestStream preloadedStream = new RequestStream(preloadedEntityBody, boundaryData,
- null, RequestStream.FileStatus.Close, RequestStream.ReadStatus.NoRead, uploadFolder, isUploadFinished, application.Context, string.Empty);
- readBody.AddRange(preloadedStream.ReadBody);
- //Set upload status.
- if (uploadGuid != string.Empty)
- {
- uploadStatus.FileLength = FileLength;
- uploadStatus.ReceivedLength = currentPosition;
- uploadStatus.FileName = preloadedStream.OriginalFileName;
- uploadStatus.FileCount = ((Hashtable) application.Context.Items["Sunrise_Web_Upload_FileList"]).Count;
- application.Application[("_UploadGUID_" + uploadGuid)] = uploadStatus;
- }
- //Is all data have been preload?
- if (!workerRequest.IsEntireEntityBodyIsPreloaded())
- {
- byte[] boudaryContent;
- ArrayList contentBody;
- //Define size of boundary.
- int boundarySize = 204800;
- byte[] boudaryBuffer = new byte[boundarySize];
- //Read each data block into read body array.
- while (((FileLength - currentPosition) >= boundarySize))
- {
- //If client is disconnected, clear all resources in use.
- if (!application.Context.Response.IsClientConnected)
- {
- this.ReleaseRes(application);
- }
- //Read bytes from request.
- boundarySize = workerRequest.ReadEntityBody(boudaryBuffer, boudaryBuffer.Length);
- currentPosition += boundarySize;
- contentBody = preloadedStream.ContentBody;
- if (contentBody.Count > 0)
- {
- boudaryContent = new byte[(contentBody.Count + boudaryBuffer.Length)];
- contentBody.CopyTo(boudaryContent, 0);
- boudaryBuffer.CopyTo(boudaryContent, contentBody.Count);
- preloadedStream = new RequestStream(boudaryContent, boundaryData,
- preloadedStream.FileStream, preloadedStream.FStatus, preloadedStream.RStatus, uploadFolder, isUploadFinished, application.Context, preloadedStream.OriginalFileName);
- }
- else
- {
- preloadedStream = new RequestStream(boudaryBuffer, boundaryData,
- preloadedStream.FileStream, preloadedStream.FStatus, preloadedStream.RStatus, uploadFolder, isUploadFinished, application.Context, preloadedStream.OriginalFileName);
- }
- //Append data block to read body array
- readBody.AddRange(preloadedStream.ReadBody);
- //Set upload status.
- if (uploadGuid != string.Empty)
- {
- uploadStatus.ReceivedLength = currentPosition;
- uploadStatus.FileName = preloadedStream.OriginalFileName;
- uploadStatus.FileCount = ((Hashtable) application.Context.Items["Sunrise_Web_Upload_FileList"]).Count;
- application.Application[("_UploadGUID_" + uploadGuid)] = uploadStatus;
- }
- }
- //The rest request data
- boudaryBuffer = new byte[FileLength - currentPosition];
- if (!application.Context.Response.IsClientConnected
- && (preloadedStream.FStatus == RequestStream.FileStatus.Open))
- {
- this.ReleaseRes(application);
- }
- //Size of spare request data.
- boundarySize = workerRequest.ReadEntityBody(boudaryBuffer, boudaryBuffer.Length);
- contentBody = preloadedStream.ContentBody;
- if (contentBody.Count > 0)
- {
- boudaryContent = new byte[(contentBody.Count + boudaryBuffer.Length)];
- contentBody.CopyTo(boudaryContent, 0);
- boudaryBuffer.CopyTo(boudaryContent, contentBody.Count);
- preloadedStream = new RequestStream(boudaryContent, boundaryData, preloadedStream.FileStream, preloadedStream.FStatus, preloadedStream.RStatus, uploadFolder, isUploadFinished, application.Context, preloadedStream.OriginalFileName);
- }
- else
- {
- preloadedStream = new RequestStream(boudaryBuffer, boundaryData, preloadedStream.FileStream, preloadedStream.FStatus, preloadedStream.RStatus, uploadFolder, isUploadFinished, application.Context, preloadedStream.OriginalFileName);
- }
- //Append the rest data block to read body array.
- readBody.AddRange(preloadedStream.ReadBody);
- if (uploadGuid != string.Empty)
- {
- uploadStatus.ReceivedLength = (currentPosition + boudaryBuffer.Length);
- uploadStatus.FileName = preloadedStream.OriginalFileName;
- uploadStatus.FileCount = ((Hashtable) application.Context.Items["Sunrise_Web_Upload_FileList"]).Count;
- if (isUploadFinished)
- {
- uploadStatus.State = UploadState.Uploaded;
- }
- else
- {
- application.Application.Remove(("_UploadGUID_" + uploadGuid));
- }
- }
- }
- //Copy all data to byte buffer.
- byte[] readedBodyBuffer = new byte[readBody.Count];
- readBody.CopyTo(readedBodyBuffer);
- this.InjectTextParts(workerRequest, readedBodyBuffer);
- ClearApplication(application);
- }
- catch (Exception exception)
- {
- //If exception has been throw, clear all resources in use.
- this.ReleaseRes(application);
- throw exception;
- }
- }
- private HttpWorkerRequest GetWorkerRequest()
- {
- IServiceProvider provider = HttpContext.Current;
- return ((HttpWorkerRequest) provider.GetService(typeof (HttpWorkerRequest)));
- }
- private bool IsUploadRequest(HttpRequest request)
- {
- return request.ContentType.ToLower().StartsWith("multipart/form-data");
- }
- /// <summary>
- /// Even handler of end request.
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void Application_EndRequest(object sender, EventArgs e)
- {
- HttpApplication application = (sender as HttpApplication);
- application.Context.Items.Clear();
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void Application_Error(object sender, EventArgs e)
- {
- HttpApplication application = (sender as HttpApplication);
- this.ReleaseRes(application);
- }
- /// <summary>
- /// Clear all context items, delete temporary file.
- /// </summary>
- /// <param name="application"></param>
- private void ReleaseRes(HttpApplication application)
- {
- ClearApplication(application);
- if (application.Context.Items["Sunrise_Web_Upload_FileList"] != null)
- {
- Hashtable fileList = ((Hashtable) application.Context.Items["Sunrise_Web_Upload_FileList"]);
- foreach (object obj in fileList.Values)
- {
- if (!File.Exists(obj.ToString()))
- {
- continue;
- }
- File.Delete(obj.ToString());
- }
- }
- application.Context.Items.Clear();
- }
- private void ClearApplication(HttpApplication application)
- {
- if ((application.Context.Items["Sunrise_Web_Upload_FileStatus"] != null)
- && (((byte) ((RequestStream.FileStatus) application.Context.Items["Sunrise_Web_Upload_FileStatus"])) == 0))
- {
- FileStream fileStream = ((FileStream) application.Context.Items["Sunrise_Web_Upload_FileStream"]);
- fileStream.Close();
- }
-
- if (application.Context.Items["Sunrise_Web_Upload_UploadGUID"] != null)
- {
- string uploadGuid = ((string) application.Context.Items["Sunrise_Web_Upload_UploadGUID"]);
- application.Application.Remove(("_UploadGUID_" + uploadGuid));
- }
- }
- public void Dispose()
- {
-
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="application"></param>
- public void Init(HttpApplication application)
- {
- application.BeginRequest += new EventHandler(this.Application_BeginRequest);
- application.EndRequest += new EventHandler(this.Application_EndRequest);
- application.Error += new EventHandler(this.Application_Error);
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="request"></param>
- /// <param name="textParts"></param>
- /// <returns></returns>
- private byte[] InjectTextParts(HttpWorkerRequest request, byte[] textParts)
- {
- Type type;
- BindingFlags flags = (BindingFlags.NonPublic | BindingFlags.Instance);
- //Is there application host IIS6.0?
- if (Utils.GetContext().Request.ServerVariables["SERVER_SOFTWARE"].Equals("Microsoft-IIS/6.0"))
- {
- type = request.GetType().BaseType.BaseType;
- }
- else
- {
- type = request.GetType().BaseType;
- }
- int dataLength = textParts.Length;
- //Set values of working request
- type.GetField("_contentAvailLength", flags).SetValue(request, dataLength);
- type.GetField("_contentTotalLength", flags).SetValue(request, dataLength);
- type.GetField("_preloadedContent", flags).SetValue(request, textParts);
- type.GetField("_preloadedContentRead", flags).SetValue(request, true);
- return textParts;
- }
- /// <summary>
- /// Get value of "maxRequestLength" setting.
- /// </summary>
- /// <returns>
- /// If defined maxRequestLength setting in web.config
- /// and it value small then the one which defined in mechine.config, get it.
- /// Otherwise get it from mechine.config.
- /// </returns>
- private double GetUpLoadFileLength()
- {
- string assemblyLocation = typeof (string).Assembly.Location;
- assemblyLocation = Path.GetDirectoryName(assemblyLocation);
- assemblyLocation = Path.Combine(assemblyLocation, @"CONFIGmachine.config");
- XmlDocument xmlDocument = new XmlDocument();
- //Load mechine.config
- xmlDocument.Load(assemblyLocation);
- double maxRequestLength = Convert.ToDouble(xmlDocument.SelectSingleNode("configuration/system.web/httpRuntime/@maxRequestLength").Value);
- //Load web.config.
- xmlDocument.Load(Path.Combine(Utils.GetContext().Request.PhysicalApplicationPath, "web.config"));
- XmlNode node = xmlDocument.SelectSingleNode("configuration/system.web/httpRuntime/@maxRequestLength");
- if (node != null)
- {
- double length = Convert.ToDouble(node.Value);
- if (length < maxRequestLength)
- {
- maxRequestLength = length;
- }
- }
- //Release xml document object.
- xmlDocument = null;
- return (maxRequestLength*1024);
- }
- }
- }