// Not safe for overlapped writes. internal Task SendAsync(string fileName, long offset, long?length, CancellationToken cancel) { cancel.ThrowIfCancellationRequested(); if (string.IsNullOrWhiteSpace(fileName)) { throw new ArgumentNullException("fileName"); } if (!File.Exists(fileName)) { throw new FileNotFoundException(string.Empty, fileName); } var fileInfo = new FileInfo(fileName); if (offset < 0 || offset > fileInfo.Length) { throw new ArgumentOutOfRangeException("offset", offset, string.Empty); } if (length.HasValue && (length.Value < 0 || length.Value > fileInfo.Length - offset)) { throw new ArgumentOutOfRangeException("length", length, string.Empty); } Stream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 1024 * 64, FileOptions.Asynchronous | FileOptions.SequentialScan); try { fileStream.Seek(offset, SeekOrigin.Begin); var copyOperation = new StreamCopyOperation(fileStream, _output, length, cancel); return(copyOperation.Start() .ContinueWith(resultTask => { fileStream.Close(); resultTask.Wait(); // Throw exceptions, etc. }, TaskContinuationOptions.ExecuteSynchronously)); } catch (Exception) { fileStream.Close(); throw; } }
// 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 Task SendAsync() { ApplyResponseHeaders(Constants.Status200Ok); string physicalPath = _fileInfo.PhysicalPath; SendFileFunc sendFile = _response.Get <SendFileFunc>(Constants.SendFileAsyncKey); if (sendFile != null && !string.IsNullOrEmpty(physicalPath)) { return(sendFile(physicalPath, 0, _length, _request.CallCancelled)); } Stream readStream = _fileInfo.CreateReadStream(); var copyOperation = new StreamCopyOperation(readStream, _response.Body, _length, _request.CallCancelled); Task task = copyOperation.Start(); task.ContinueWith(resultTask => readStream.Close(), TaskContinuationOptions.ExecuteSynchronously); return(task); }
public Task SendAsync(int statusCode) { _response.StatusCode = statusCode; _response.SetHeader(Constants.ContentLength, _length.ToString(CultureInfo.InvariantCulture)); string physicalPath = _fileInfo.PhysicalPath; if (_response.CanSendFile && !string.IsNullOrEmpty(physicalPath)) { return(_response.SendFileAsync(physicalPath, 0, _length, _request.CallCancelled)); } Stream readStream = _fileInfo.CreateReadStream(); var copyOperation = new StreamCopyOperation(readStream, _response.Body, _length, _request.CallCancelled); Task task = copyOperation.Start(); task.ContinueWith(resultTask => readStream.Close(), TaskContinuationOptions.ExecuteSynchronously); return(task); }
// Not safe for overlapped writes. internal Task SendAsync(string fileName, long offset, long? length, CancellationToken cancel) { cancel.ThrowIfCancellationRequested(); if (string.IsNullOrWhiteSpace(fileName)) { throw new ArgumentNullException("fileName"); } if (!File.Exists(fileName)) { throw new FileNotFoundException(string.Empty, fileName); } var fileInfo = new FileInfo(fileName); if (offset < 0 || offset > fileInfo.Length) { throw new ArgumentOutOfRangeException("offset", offset, string.Empty); } if (length.HasValue && (length.Value < 0 || length.Value > fileInfo.Length - offset)) { throw new ArgumentOutOfRangeException("length", length, string.Empty); } Stream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 1024 * 64, FileOptions.Asynchronous | FileOptions.SequentialScan); try { fileStream.Seek(offset, SeekOrigin.Begin); var copyOperation = new StreamCopyOperation(fileStream, _output, length, cancel); return copyOperation.Start() .ContinueWith(resultTask => { fileStream.Close(); resultTask.Wait(); // Throw exceptions, etc. }, TaskContinuationOptions.ExecuteSynchronously); } catch (Exception) { fileStream.Close(); throw; } }
public Task SendAsync(int statusCode) { _response.StatusCode = statusCode; _response.SetHeader(Constants.ContentLength, _length.ToString(CultureInfo.InvariantCulture)); string physicalPath = _fileInfo.PhysicalPath; if (_response.CanSendFile && !string.IsNullOrEmpty(physicalPath)) { return _response.SendFileAsync(physicalPath, 0, _length, _request.CallCancelled); } Stream readStream = _fileInfo.CreateReadStream(); var copyOperation = new StreamCopyOperation(readStream, _response.Body, _length, _request.CallCancelled); Task task = copyOperation.Start(); task.ContinueWith(resultTask => readStream.Close(), TaskContinuationOptions.ExecuteSynchronously); return task; }
// 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 Task SendAsync() { ApplyResponseHeaders(Constants.Status200Ok); string physicalPath = _fileInfo.PhysicalPath; SendFileFunc sendFile = _response.Get<SendFileFunc>(Constants.SendFileAsyncKey); if (sendFile != null && !string.IsNullOrEmpty(physicalPath)) { return sendFile(physicalPath, 0, _length, _request.CallCancelled); } Stream readStream = _fileInfo.CreateReadStream(); var copyOperation = new StreamCopyOperation(readStream, _response.Body, _length, _request.CallCancelled); Task task = copyOperation.Start(); task.ContinueWith(resultTask => readStream.Close(), TaskContinuationOptions.ExecuteSynchronously); return task; }