/// <summary> /// Waits for the current upload request to finish.</summary> /// <remarks> /// <para> /// If the UploadHttpModule is being used for the current request, this method will not return until the /// module has received and processed the entire request. If the UploadHttpModule is not being used for /// the current request, this method will return immediately. Note: the UploadHttpModule is only used if /// it has been added in the httpModules section of the Web.config, the neatUpload section's /// useHttpModule attribute is "true" for the page being requested (which is the default), and the /// request has a content type of multipart/form-data.</para> /// </remarks> public static void WaitForUploadToComplete() { // If the original request hasn't been parsed (and any upload received) by now, // we force parsing to ensure that the upload is received. FilteringWorkerRequest worker = GetCurrentWorkerRequest() as FilteringWorkerRequest; if (worker != null) { worker.ParseMultipart(); } }
private void Application_BeginRequest(object sender, EventArgs e) { if (log.IsDebugEnabled) { log.Debug("In Application_BeginRequest"); } // When tracing is enabled at the application level ASP.NET reads the entire request before // BeginRequest is fired. So, we should not use our module at all. We can't do this // check from Init() when using Integrated Pipeline Mode because the following line // will throw an exception if tracing is enabled. lock (StaticSync) { _isInited = !HttpContext.Current.Trace.IsEnabled; if (!IsInited) { return; } } HttpApplication app = sender as HttpApplication; // Restore the cookies for the MultiRequestUploadModule.UploadPath page. HttpWorkerRequest wr = GetCurrentWorkerRequest(); string filePath = wr.GetFilePath().ToLower(); string multiRequestUploadPath = MultiRequestUploadModule.UploadPath; multiRequestUploadPath = app.Response.ApplyAppPathModifier(multiRequestUploadPath); if (log.IsDebugEnabled) { log.DebugFormat("filePath={0}", filePath); } string qs = wr.GetQueryString(); if (filePath.StartsWith(multiRequestUploadPath.ToLower())) { // The module should always be used for the multi-request upload handler // Note that for compatibility reasons we can't set useHttpModule="true" // in the NeatUpload folder's Web.config because we can't be sure where // the app put the top-level <neatUpload> section and if guess wrong we // won't inherit the top-level settings (e.g. validationKey and // encryptionKey) HttpContext.Current.Items["NeatUpload_UseHttpModule"] = true; if (qs != null) { HttpCookieCollection cookies = UploadHttpModule.GetCookiesFromQueryString(qs); if (log.IsDebugEnabled) { log.DebugFormat("cookies={0}", cookies); } if (cookies != null) { foreach (string k in cookies.AllKeys) { HttpCookie c = cookies[k]; if (log.IsDebugEnabled) { log.DebugFormat("Calling SetCookie({0}, {1})", c.Name, c.Value); } SetCookie(c.Name, c.Value); } } } } if (!Config.Current.UseHttpModule) { return; } HttpWorkerRequest origWorker = GetCurrentWorkerRequest(); if (origWorker == null) { if (log.IsDebugEnabled) { log.Debug("origWorker = null"); } return; } if (log.IsDebugEnabled) { log.Debug(origWorker.GetType() + " for " + origWorker.GetRawUrl() + " with AspFilterSessionId = " + origWorker.GetUnknownRequestHeader("AspFilterSessionId")); } string rawUrl = app.Context.Request.RawUrl; log4net.ThreadContext.Properties["url"] = rawUrl; if (origWorker is DecoratedWorkerRequest) { // If an unhandled error occurs, we want to remember it so that we can rethrow it // in the original context. if (RememberErrorHandler != null) { app.Error += RememberErrorHandler; } // Save a reference to the original HttpContext in the subrequest context so that // AppendToLog() can use it. DecoratedWorkerRequest decoratedWorkerRequest = origWorker as DecoratedWorkerRequest; if (decoratedWorkerRequest.OrigContext != null) { HttpContext.Current.Items["NeatUpload_origContext"] = decoratedWorkerRequest.OrigContext; } // Ignore the subrequests to avoid infinite recursion... return; } // Get the Content-Length header and parse it if we find it. If it's not present we might // still be OK. long contentLength = 0; string contentLengthHeader = origWorker.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentLength); if (contentLengthHeader != null) { try { contentLength = Int64.Parse(contentLengthHeader); } catch (Exception ex) { throw new HttpException(400, "Bad Request", ex); } } DecoratedWorkerRequest subWorker = null; // Create a subrequest for each request. For multipart/form-data requests, we use a // FilteringWorkerRequest which filters the file parts into temp files. For all other // requests that could contain a body, we use a SizeLimitingWorkerRequest to ensure that the // size of the request is within // the user configured limit. We need the SizeLimitingWorkerRequest, because httpRuntime's // maxRequestLength attribute needs to be set to a large value to allow large file upload request // to get to this module at all. That means that large normal requests will also get to this // module. SizeLimitingWorkerRequest ensures that normal requests which are too large are // rejected. string contentTypeHeader = origWorker.GetKnownRequestHeader(HttpWorkerRequest.HeaderContentType); string transferEncodingHeader = origWorker.GetKnownRequestHeader(HttpWorkerRequest.HeaderTransferEncoding); if (contentTypeHeader != null && contentTypeHeader.ToLower().StartsWith("multipart/form-data")) { // If this is a multi-request upload get the post-back ID from the query string if (qs != null && UploadHttpModule.GetMultiRequestControlIDFromQueryString(qs) != null) { CurrentUploadState = UploadStateStore.OpenReadWriteOrCreate(UploadHttpModule.GetPostBackIDFromQueryString(qs)); if (transferEncodingHeader != "chunked") { CurrentUploadState.Status = UploadStatus.NormalInProgress; } else { CurrentUploadState.Status = UploadStatus.ChunkedInProgress; } } subWorker = new FilteringWorkerRequest(origWorker); } else { // If the client-specified content length is too large, we reject the request // immediately. If it's not, the client could be lying so we need to use // SizeLimitingWorkerRequest to actually count the bytes. if (contentLength > MaxNormalRequestLength) { throw new HttpException(413, "Request Entity Too Large"); } // Only requests which match the following criteria could contain a body. if ((transferEncodingHeader != null && transferEncodingHeader != "identity") || (contentLengthHeader != null && contentLengthHeader != "0") || (contentTypeHeader != null && contentTypeHeader.StartsWith("multipart/byteranges"))) { subWorker = new SizeLimitingWorkerRequest(origWorker, MaxNormalRequestLength); } else { if (origWorker.HasEntityBody()) { throw new HttpException(400, "Unexpected body in request for " + rawUrl); } } } if (subWorker != null) { if (!ReplaceWorkerRequest(app, subWorker)) { MakeChildRequest(app, subWorker); } } }