private void HandleStreamWriteStatus(StreamWriteStatus fileSendStatus) { switch (fileSendStatus) { case StreamWriteStatus.UnexpectedError: _statusLogger.Log(this._context, StreamWriteStatus.UnexpectedError); //log.Error(String.Format("Unexpected File Transfer Error - Identity [{0}] - FileId [{1}] - User Id [{2}] / Name [{3}] / Email [{4}]{5}File Path [ {6} ]{5}{5}{7}", WindowsIdentity.GetCurrent().Name, FileId, context.OnyxUser().Identity.OCPUser.Individual.OnyxId, context.OnyxUser().Identity.OCPUser.Individual.UserName, context.OnyxUser().Identity.OCPUser.Individual.UserEmailAddress, Environment.NewLine, properties.MappedPath, this._request.ToLogString())); SafeInternalServerError(this._context, this._configuration.ServerErrorUrl); break; case StreamWriteStatus.StreamReadError: _statusLogger.Log(this._context, StreamWriteStatus.StreamReadError); //log.Error(String.Format("File Could Not Be Read - Identity [{0}] - FileId [{1}] - User Id [{2}] / Name [{3}] / Email [{4}]{5}File Path [ {6} ]{5}{5}{7}", WindowsIdentity.GetCurrent().Name, FileId, context.OnyxUser().Identity.OCPUser.Individual.OnyxId, context.OnyxUser().Identity.OCPUser.Individual.UserName, context.OnyxUser().Identity.OCPUser.Individual.UserEmailAddress, Environment.NewLine, properties.MappedPath, this._request.ToLogString())); SafeInternalServerError(this._context, this._configuration.ServerErrorUrl); break; //nothing to do here case StreamWriteStatus.SentHttpHead: case StreamWriteStatus.SentFile: case StreamWriteStatus.ClientDisconnected: default: break; } }
/// <summary> Stream file. </summary> /// <remarks> ebrown, 2/15/2011. </remarks> /// <exception cref="ArgumentNullException"> Thrown when one or more required arguments are null. </exception> /// <exception cref="Exception"> Thrown when exception. </exception> /// <param name="requestedResponseType"> Type of the requested response. </param> /// <param name="downloadProperties"> The download properties. </param> /// <param name="rangeRequests"> The range requests. </param> /// <param name="ifRangeEntityTag"> if range entity tag. </param> /// <param name="forceDownload"> true to force download. </param> /// <returns> . </returns> public StreamWriteStatus StreamFile(HttpResponseType requestedResponseType, StreamLoaderResult downloadProperties, IEnumerable <RangeRequest> rangeRequests, string ifRangeEntityTag, bool forceDownload) { if (null == downloadProperties) { throw new ArgumentNullException("downloadProperties"); } if (null == rangeRequests) { throw new ArgumentNullException("rangeRequests"); } try { string contentType = !string.IsNullOrEmpty(downloadProperties.ContentType) ? downloadProperties.ContentType : MimeTypes.GetMimeTypeForFileExtension(Path.GetExtension(downloadProperties.Metadata.FileName)); if (forceDownload) { this._response.AppendHeader("content-disposition", String.Format(CultureInfo.InvariantCulture, "attachment; filename={0}", downloadProperties.Metadata.FileName)); } bool isMultipart = RangeRequestHelpers.IsMultipartRequest(rangeRequests), isActionableRangeRequest = IsActionableRangeRequest(downloadProperties.Metadata, rangeRequests, ifRangeEntityTag); //TODO: is this response.Clear() necessary here? this._response.Clear(); long responseContentLength = CalculateContentLength(downloadProperties.Metadata, rangeRequests, ifRangeEntityTag, contentType, isMultipart); this._response.StatusCode = isActionableRangeRequest ? (int)HttpStatusCode.PartialContent : (int)HttpStatusCode.OK; if (isActionableRangeRequest && !isMultipart) { var first = rangeRequests.First(); //must indicate the Response Range of in the initial HTTP Header since this isn't multipart this._response.AppendHeader(HttpHeaderFields.ContentRange.ToEnumValueString(), String.Format(CultureInfo.InvariantCulture, "bytes {0}-{1}/{2}", first.Start, first.End, downloadProperties.Metadata.Size.Value)); } this._response.AppendHeader(HttpHeaderFields.ContentLength.ToEnumValueString(), responseContentLength.ToString(CultureInfo.InvariantCulture)); //don't go off the DB insert date for last modified b/c the file system file could be older (b/c multiple files records inserted at different dates could share the same physical file) if (downloadProperties.Metadata.LastWriteTimeUtc.HasValue) { this._response.AppendHeader(HttpHeaderFields.LastModified.ToEnumValueString(), downloadProperties.Metadata.LastWriteTimeUtc.Value.ToString("r", CultureInfo.InvariantCulture)); } this._response.AppendHeader(HttpHeaderFields.AcceptRanges.ToEnumValueString(), "bytes"); this._response.AppendHeader(HttpHeaderFields.EntityTag.ToEnumValueString(), String.Format(CultureInfo.InvariantCulture, "\"{0}\"", downloadProperties.Metadata.ExpectedMD5)); //not sure if we should use the Keep-Alive header? //this._response.AppendHeader(HttpHeaderFields.HTTP_HEADER_KEEP_ALIVE, "timeout=15, max=30"); //multipart messages are special -> file's actual mime type written into Response later this._response.ContentType = (isMultipart ? MultipartNames.MultipartContentType : contentType); //we've dumped our HEAD and can return now if (HttpResponseType.HeadOnly == requestedResponseType) { // Flush the HEAD information to the client... this._response.Flush(); return(StreamWriteStatus.SentHttpHead); } StreamWriteStatus result = BufferStreamToResponse(downloadProperties, rangeRequests, contentType); return((StreamWriteStatus.ClientDisconnected == result) ? result : StreamWriteStatus.SentFile); //this causes a ThreadAbortException //Response.End(); } catch (IOException ex) { string userName = string.Empty; using (var identity = WindowsIdentity.GetCurrent()) { userName = identity.Name; } //, this._request.ToLogString() log.Error(String.Format(CultureInfo.InvariantCulture, "File read failure for user {0}", userName), ex); return(StreamWriteStatus.StreamReadError); } catch (Exception ex) { HttpException httpEx = ex as HttpException; //suck up the remote connection failure if ((null != httpEx) && (HttpExceptionErrorCodes.ConnectionAborted == httpEx.ErrorCode)) { return(StreamWriteStatus.ClientDisconnected); } //bubble up to the caller, and let them log it -- this maintains the identity of our original exception as the innerexception throw; //log.Error("Unexpected failure for " + WindowsIdentity.GetCurrent().Name, ex); //error = "Unexpected File Transfer Error - FileId [" + FileId.ToString() + "] - User Id [" + context.OnyxUser().Identity.OCPUser.Individual.OnyxId.ToString() + "] / Name [" + ((userProperties.Name == null) ? string.Empty : userProperties.Name) + "] / Email [" + ((userProperties.Email == null) ? string.Empty : userProperties.Email) + "]" + Environment.NewLine + "File Path [ " + properties.MappedPath + " ]"; //return DownloadFileStatus.UnexpectedError; } }