// When there is only a single range the bytes are sent directly in the body. internal Task SendRangeAsync() { bool rangeNotSatisfiable = false; if (_ranges.Count == 0) { rangeNotSatisfiable = true; } if (rangeNotSatisfiable) { // 14.16 Content-Range - A server sending a response with status code 416 (Requested range not satisfiable) // SHOULD include a Content-Range field with a byte-range-resp-spec of "*". The instance-length specifies // the current length of the selected resource. e.g. */length _response.Headers[Constants.ContentRange] = "bytes */" + _length.ToString(CultureInfo.InvariantCulture); ApplyResponseHeaders(Constants.Status416RangeNotSatisfiable); return(Constants.CompletedTask); } // Multi-range is not supported. Debug.Assert(_ranges.Count == 1); long start, length; _response.Headers[Constants.ContentRange] = ComputeContentRange(_ranges[0], out start, out length); _response.ContentLength = length; ApplyResponseHeaders(Constants.Status206PartialContent); string physicalPath = _fileInfo.PhysicalPath; SendFileFunc sendFile = _response.Get <SendFileFunc>(Constants.SendFileAsyncKey); if (sendFile != null && !string.IsNullOrEmpty(physicalPath)) { return(sendFile(physicalPath, start, length, _request.CallCancelled)); } Stream readStream = _fileInfo.CreateReadStream(); readStream.Seek(start, SeekOrigin.Begin); // TODO: What if !CanSeek? var copyOperation = new StreamCopyOperation(readStream, _response.Body, length, _request.CallCancelled); Task task = copyOperation.Start(); task.ContinueWith(resultTask => readStream.Close(), TaskContinuationOptions.ExecuteSynchronously); return(task); }
public async Task SendAsync() { ApplyResponseHeaders(Constants.Status200Ok); string physicalPath = _fileInfo.PhysicalPath; SendFileFunc sendFile = _response.Get <SendFileFunc>(Constants.SendFileAsyncKey); if (sendFile != null && !string.IsNullOrEmpty(physicalPath)) { await sendFile(physicalPath, 0, _length, _request.CallCancelled); } Stream readStream = _fileInfo.CreateReadStream(); var copyOperation = new StreamCopyOperation(readStream, _response.Body, _length, _request.CallCancelled); await copyOperation.Start(); readStream.Close(); }