public override void ExecuteResult(ControllerContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } ResumeRequest resumingRequest = new ResumeRequest(context.HttpContext, FileContents.Length) { FileName = _fileName }; context.HttpContext.Response.Headers[HttpHeaders.AccessControlExposeHeaders] = HttpHeaders.ContentDisposition; ExecuteResultBody(context, resumingRequest); }
public virtual void ExecuteResultBody(ControllerContext context, ResumeRequest resumingRequest) { WriteCommonHeaders(context, resumingRequest); if (ShouldProceedAfterEvaluatingPreconditions(context.HttpContext, resumingRequest)) { using (FileContents) { if (resumingRequest.IsRangeRequest) { WritePartialContent(context, FileContents, resumingRequest); } else { WriteFullContent(context, FileContents); } } } }
protected virtual void WriteCommonHeaders(ControllerContext context, ResumeRequest resumingRequest) { context.HttpContext.Response.ContentType = resumingRequest.IsMultipartRequest ? $"multipart/byteranges; boundary={MultipartBoundary}" : ContentType; context.HttpContext.Response.AddHeader(HttpWorkerRequest.GetKnownResponseHeaderName(HttpWorkerRequest.HeaderAcceptRanges), "bytes"); if (!string.IsNullOrEmpty(resumingRequest.FileName)) { context.HttpContext.Response.AddHeader("Content-Disposition", $"inline; filename=\"{resumingRequest.FileName}\""); } if (!string.IsNullOrEmpty(EntityTag)) { context.HttpContext.Response.AddHeader(HttpWorkerRequest.GetKnownResponseHeaderName(HttpWorkerRequest.HeaderEtag), EntityTag); } if (LastModified.HasValue) { context.HttpContext.Response.AddHeader(HttpWorkerRequest.GetKnownResponseHeaderName(HttpWorkerRequest.HeaderLastModified), LastModified.Value.ToString("R")); } }
protected virtual bool ShouldProceedAfterEvaluatingPreconditions(HttpContextBase context, ResumeRequest resumingRequest) { var request = context.Request; string check; DateTimeOffset preconditionDateTime; if (!string.IsNullOrEmpty(check = (request.Headers[HttpWorkerRequest.GetKnownRequestHeaderName(HttpWorkerRequest.HeaderIfRange)]))) { if (DateTimeOffset.TryParse(check, out preconditionDateTime)) { if ((LastModified.Value - preconditionDateTime).TotalSeconds > 1) { resumingRequest.Ranges = null; } } else { if (!check.Equals(EntityTag)) { resumingRequest.Ranges = null; } } } if (!string.IsNullOrEmpty(check = (request.Headers[HttpWorkerRequest.GetKnownRequestHeaderName(HttpWorkerRequest.HeaderIfMatch)]))) { IEnumerable <string> entitiesTags = check.Split(','); if ((string.IsNullOrEmpty(EntityTag) && entitiesTags.Any()) || (!entitiesTags.Any(entity => entitiesTags.Equals(EntityTag)))) { context.Response.StatusCode = (int)HttpStatusCode.PreconditionFailed; return(false); } } if (!string.IsNullOrEmpty(check = (request.Headers[HttpWorkerRequest.GetKnownRequestHeaderName(HttpWorkerRequest.HeaderIfNoneMatch)]))) { IEnumerable <string> entitiesTag = check.Split(','); if ((!string.IsNullOrEmpty(EntityTag) && entitiesTag.Contains("*")) || (entitiesTag.Any(entity => entity.Equals(EntityTag)))) { if (context.Request.RequestType == "GET" || context.Request.RequestType == "HEAD") { context.Response.StatusCode = (int)HttpStatusCode.NotModified; return(false); } else { context.Response.StatusCode = (int)HttpStatusCode.PreconditionFailed; return(false); } } } if (!string.IsNullOrEmpty(check = (request.Headers[HttpWorkerRequest.GetKnownRequestHeaderName(HttpWorkerRequest.HeaderIfUnmodifiedSince)]))) { if (DateTimeOffset.TryParse(check, out preconditionDateTime)) { if (!LastModified.HasValue || ((LastModified.Value - preconditionDateTime).TotalSeconds > 0)) { context.Response.StatusCode = (int)HttpStatusCode.PreconditionFailed; return(false); } } } if (!string.IsNullOrEmpty(check = (request.Headers[HttpWorkerRequest.GetKnownRequestHeaderName(HttpWorkerRequest.HeaderIfModifiedSince)]))) { if (DateTimeOffset.TryParse(check, out preconditionDateTime)) { if (LastModified.HasValue) { if ((LastModified.Value - preconditionDateTime).TotalSeconds < 1) { context.Response.StatusCode = (int)HttpStatusCode.NotModified; return(false); } } } } return(true); }
public virtual void WritePartialContent(ControllerContext context, Stream fileContent, ResumeRequest resumingRequest) { var response = context.HttpContext.Response; response.StatusCode = (int)HttpStatusCode.PartialContent; if (!resumingRequest.IsMultipartRequest) { context.HttpContext.Response.AddHeader(HttpWorkerRequest.GetKnownResponseHeaderName(HttpWorkerRequest.HeaderContentRange), $"bytes {resumingRequest.Ranges.First().Start}-{resumingRequest.Ranges.First().End}/{fileContent.Length}"); } foreach (var range in resumingRequest.Ranges) { if (!response.IsClientConnected) { return; } if (resumingRequest.IsMultipartRequest) { response.Output.WriteLine($"--{MultipartBoundary}"); response.Output.WriteLine($"{HttpWorkerRequest.GetKnownResponseHeaderName(HttpWorkerRequest.HeaderContentType)}: {ContentType}"); response.Output.WriteLine($"{HttpWorkerRequest.GetKnownResponseHeaderName(HttpWorkerRequest.HeaderContentRange)}: bytes {resumingRequest.Ranges.First().Start}-{resumingRequest.Ranges.First().End}/{fileContent.Length}"); response.Output.WriteLine(); } WriteBinaryData(context, fileContent, range.Start, range.End); if (resumingRequest.IsMultipartRequest) { response.Output.WriteLine(); } } if (resumingRequest.IsMultipartRequest) { response.Output.WriteLine($"--{MultipartBoundary}--"); response.Output.WriteLine(); } }