public EntityResponseSinglePart(IHttpResponseHeaderHelper httpResponseHeaderHelper, RangeItem range) { this.HttpResponseHeaderHelper = httpResponseHeaderHelper; this.Range = range; }
/// <summary> /// Parses the Range Header from the http request. /// </summary> /// <param name="request"></param> /// <param name="contentLength">The length of the content to serve.</param> /// <param name="ranges">A list of ranges</param> /// <returns> /// Returns Null, if there is no Range Header in the http request /// Return False, if there are unsatisfiable Range Headers in the http request (416 Requested Range Not Satisfiable) /// Returns True, if there are Range Headers in the http request /// </returns> public bool? GetRanges(HttpRequestBase request, long contentLength, out IEnumerable<RangeItem> ranges) { var requestHeaderRange = GetHttpHeaderValue(request, HttpRequestHeader.Range, String.Empty); var rangesResult = new List<RangeItem>(); if (string.IsNullOrEmpty(requestHeaderRange)) { ranges = rangesResult; return null; } var rangesString = requestHeaderRange.Replace(" ", "").Replace("bytes=", "").Split(",".ToCharArray()); // Check each found Range request for consistency foreach (var rangeString in rangesString) { // Split this range request by the dash character, // currentRange[0] contains the requested begin-value, // currentRange[1] contains the requested end-value... var currentRangeString = rangeString.Split("-".ToCharArray()); if (currentRangeString.Length != 2) { ranges = null; return false; } var currentRange = new RangeItem(); // Determine the end of the requested range if (string.IsNullOrEmpty(currentRangeString[1])) { // No end was specified, take the entire range currentRange.EndRange = contentLength - 1; } else { // An end was specified... int endRangeValue; if (!int.TryParse(currentRangeString[1], out endRangeValue)) { ranges = null; return false; } currentRange.EndRange = endRangeValue; } // Determine the begin of the requested range if (string.IsNullOrEmpty(currentRangeString[0])) { // No begin was specified, which means that // the end value indicated to return the last n // bytes of the file: // Calculate the begin currentRange.StartRange = contentLength - currentRange.EndRange; // ... to the end of the file... currentRange.EndRange = contentLength - 1; } else { // A normal begin value was indicated... int beginRangeValue; if (!int.TryParse(currentRangeString[0], out beginRangeValue)) { ranges = null; return false; } currentRange.StartRange = beginRangeValue; } // Check if the requested range values are valid, // return False if they are not. // Note: // Do not clean invalid values up by fitting them into // valid parameters using Math.Min and Math.Max, because // some download clients (like Go!Zilla) might send invalid // (e.g. too large) range requests to determine the file limits! // Begin and end must not exceed the file size if ((currentRange.StartRange > (contentLength - 1)) | (currentRange.EndRange > (contentLength - 1))) { ranges = null; return false; } // Begin and end cannot be < 0 if ((currentRange.StartRange < 0) | (currentRange.EndRange < 0)) { ranges = null; return false; } // End must be larger or equal to begin value if (currentRange.EndRange < currentRange.StartRange) { // The requested Range is invalid... ranges = null; return false; } //We reached here so its a valid range, so add it to the list of ranges rangesResult.Add(currentRange); } ranges = rangesResult; return true; }