예제 #1
0
        public async Task SendAsync()
        {
            ApplyResponseHeaders(Constants.Status200Ok);

            string physicalPath = _fileInfo.PhysicalPath;
            var    sendFile     = _context.Features.Get <IHttpSendFileFeature>();

            if (sendFile != null && !string.IsNullOrEmpty(physicalPath))
            {
                await sendFile.SendFileAsync(physicalPath, 0, _length, _context.RequestAborted);

                return;
            }

            Stream readStream = _fileInfo.CreateReadStream();

            try
            {
                await StreamCopyOperation.CopyToAsync(readStream, _response.Body, _length, _context.RequestAborted);
            }
            finally
            {
                readStream.Dispose();
            }
        }
예제 #2
0
        // When there is only a single range the bytes are sent directly in the body.
        internal async 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
                _responseHeaders.ContentRange = new ContentRangeHeaderValue(_length);
                ApplyResponseHeaders(Constants.Status416RangeNotSatisfiable);
                _logger.LogWarning("Range not satisfiable for {0}", SubPath);
                return;
            }

            // Multi-range is not supported.
            Debug.Assert(_ranges.Count == 1);

            long start, length;

            _responseHeaders.ContentRange = ComputeContentRange(_ranges[0], out start, out length);
            _response.ContentLength       = length;
            ApplyResponseHeaders(Constants.Status206PartialContent);

            string physicalPath = _fileInfo.PhysicalPath;
            var    sendFile     = _context.Features.Get <IHttpSendFileFeature>();

            if (sendFile != null && !string.IsNullOrEmpty(physicalPath))
            {
                if (_logger.IsEnabled(LogLevel.Verbose))
                {
                    _logger.LogVerbose(string.Format("Sending {0} of file {1}", _response.Headers[HeaderNames.ContentRange], physicalPath));
                }
                await sendFile.SendFileAsync(physicalPath, start, length, _context.RequestAborted);

                return;
            }

            Stream readStream = _fileInfo.CreateReadStream();

            try
            {
                readStream.Seek(start, SeekOrigin.Begin); // TODO: What if !CanSeek?
                if (_logger.IsEnabled(LogLevel.Verbose))
                {
                    _logger.LogVerbose(string.Format("Copying {0} of file {1} to the response body", _response.Headers[HeaderNames.ContentRange], SubPath));
                }
                await StreamCopyOperation.CopyToAsync(readStream, _response.Body, length, _context.RequestAborted);
            }
            finally
            {
                readStream.Dispose();
            }
        }
예제 #3
0
            // Not safe for overlapped writes.
            public async Task SendFileAsync(string fileName, long offset, long?length, CancellationToken cancel)
            {
                cancel.ThrowIfCancellationRequested();

                if (string.IsNullOrWhiteSpace(fileName))
                {
                    throw new ArgumentNullException(nameof(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(nameof(offset), offset, string.Empty);
                }

                if (length.HasValue &&
                    (length.Value < 0 || length.Value > fileInfo.Length - offset))
                {
                    throw new ArgumentOutOfRangeException(nameof(length), length, string.Empty);
                }

                var fileStream = new FileStream(
                    fileName,
                    FileMode.Open,
                    FileAccess.Read,
                    FileShare.ReadWrite,
                    bufferSize: 1024 * 64,
                    options: FileOptions.Asynchronous | FileOptions.SequentialScan);

                try
                {
                    fileStream.Seek(offset, SeekOrigin.Begin);

                    _logger.LogCopyingBytesToResponse(
                        start: offset,
                        end: length != null ? (offset + length) : null,
                        path: fileName);
                    await StreamCopyOperation.CopyToAsync(fileStream, _output, length, cancel);
                }
                finally
                {
                    fileStream.Dispose();
                }
            }
예제 #4
0
            // Not safe for overlapped writes.
            public async Task SendFileAsync(string fileName, long offset, long?length, CancellationToken cancel)
            {
                cancel.ThrowIfCancellationRequested();

                if (string.IsNullOrWhiteSpace(fileName))
                {
                    throw new ArgumentNullException(nameof(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);
                }

#if DNX451
                Stream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 1024 * 64,
                                                   FileOptions.Asynchronous | FileOptions.SequentialScan);
#else
                // TODO: Bring back async when the contract gets it
                Stream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, 1024 * 64);
#endif
                try
                {
                    fileStream.Seek(offset, SeekOrigin.Begin);
                    if (_logger.IsEnabled(LogLevel.Verbose))
                    {
                        _logger.LogVerbose(string.Format("Copying bytes {0}-{1} of file {2} to response body", offset, length != null ? (offset + length).ToString() : "*", fileName));
                    }
                    await StreamCopyOperation.CopyToAsync(fileStream, _output, length, cancel);
                }
                finally
                {
                    fileStream.Dispose();
                }
            }