Exemple #1
0
    protected virtual Task WriteFileAsync(
        ActionContext context,
        FileStreamResult result,
        RangeItemHeaderValue?range,
        long rangeLength)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        if (result == null)
        {
            throw new ArgumentNullException(nameof(result));
        }

        if (range != null && rangeLength == 0)
        {
            return(Task.CompletedTask);
        }

        if (range != null)
        {
            Logger.WritingRangeToBody();
        }

        return(WriteFileAsync(context.HttpContext, result.FileStream, range, rangeLength));
    }
        internal static Task WriteFileAsyncInternal(
            HttpContext httpContext,
            IFileInfo fileInfo,
            RangeItemHeaderValue?range,
            long rangeLength,
            ILogger logger)
        {
            if (range != null && rangeLength == 0)
            {
                return(Task.CompletedTask);
            }

            var response = httpContext.Response;

            if (range != null)
            {
                logger.WritingRangeToBody();
            }

            if (range != null)
            {
                return(response.SendFileAsync(fileInfo,
                                              offset: range.From ?? 0L,
                                              count: rangeLength));
            }

            return(response.SendFileAsync(fileInfo,
                                          offset: 0,
                                          count: null));
        }
        public override bool Equals([NotNullWhen(true)] object? obj)
        {
            RangeItemHeaderValue? other = obj as RangeItemHeaderValue;

            if (other == null)
            {
                return false;
            }
            return ((_from == other._from) && (_to == other._to));
        }
        public override bool Equals(object?obj)
        {
            RangeItemHeaderValue?other = obj as RangeItemHeaderValue;

            if (other == null)
            {
                return(false);
            }
            return((_from == other._from) && (_to == other._to));
        }
        // Returns the length of a range list. E.g. "1-2, 3-4, 5-6" adds 3 ranges to 'rangeCollection'. Note that empty
        // list segments are allowed, e.g. ",1-2, , 3-4,,".
        internal static int GetRangeItemListLength(
            StringSegment input,
            int startIndex,
            ICollection <RangeItemHeaderValue> rangeCollection)
        {
            Contract.Requires(startIndex >= 0);
            Contract.Ensures((Contract.Result <int>() == 0) || (rangeCollection.Count > 0),
                             "If we can parse the string, then we expect to have at least one range item.");

            if ((StringSegment.IsNullOrEmpty(input)) || (startIndex >= input.Length))
            {
                return(0);
            }

            // Empty segments are allowed, so skip all delimiter-only segments (e.g. ", ,").
            var separatorFound = false;
            var current        = HeaderUtilities.GetNextNonEmptyOrWhitespaceIndex(input, startIndex, true, out separatorFound);

            // It's OK if we didn't find leading separator characters. Ignore 'separatorFound'.

            if (current == input.Length)
            {
                return(0);
            }

            RangeItemHeaderValue?range = null;

            while (true)
            {
                var rangeLength = GetRangeItemLength(input, current, out range);

                if (rangeLength == 0)
                {
                    return(0);
                }

                rangeCollection !.Add(range !);

                current = current + rangeLength;
                current = HeaderUtilities.GetNextNonEmptyOrWhitespaceIndex(input, current, true, out separatorFound);

                // If the string is not consumed, we must have a delimiter, otherwise the string is not a valid
                // range list.
                if ((current < input.Length) && !separatorFound)
                {
                    return(0);
                }

                if (current == input.Length)
                {
                    return(current - startIndex);
                }
            }
        }
    internal static Task WriteFileAsyncInternal(
        HttpContext httpContext,
        PhysicalFileResult result,
        RangeItemHeaderValue?range,
        long rangeLength,
        ILogger logger)
    {
        if (httpContext == null)
        {
            throw new ArgumentNullException(nameof(httpContext));
        }

        if (result == null)
        {
            throw new ArgumentNullException(nameof(result));
        }

        if (range != null && rangeLength == 0)
        {
            return(Task.CompletedTask);
        }

        var response = httpContext.Response;

        if (!Path.IsPathRooted(result.FileName))
        {
            throw new NotSupportedException(Resources.FormatFileResult_PathNotRooted(result.FileName));
        }

        if (range != null)
        {
            Log.WritingRangeToBody(logger);
        }

        if (range != null)
        {
            return(response.SendFileAsync(result.FileName,
                                          offset: range.From ?? 0L,
                                          count: rangeLength));
        }

        return(response.SendFileAsync(result.FileName,
                                      offset: 0,
                                      count: null));
    }
Exemple #7
0
 protected static async Task WriteFileAsync(HttpContext context, Stream fileStream, RangeItemHeaderValue?range, long rangeLength)
 {
     await WriteFileAsyncInternal(context, fileStream, range, rangeLength);
 }
Exemple #8
0
 protected override Task ExecuteCoreAsync(HttpContext httpContext, RangeItemHeaderValue?range, long rangeLength)
 {
     return(_streamWriterCallback(httpContext.Response.Body));
 }
 /// <inheritdoc/>
 protected virtual Task WriteFileAsync(ActionContext context, PhysicalFileResult result, RangeItemHeaderValue?range, long rangeLength)
 {
     return(WriteFileAsyncInternal(context.HttpContext, result, range, rangeLength, Logger));
 }
Exemple #10
0
        /// <inheritdoc />
        protected override Task WriteFileAsync(ActionContext context, PhysicalFileResult result, RangeItemHeaderValue?range, long rangeLength)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }

            if (range != null && rangeLength == 0)
            {
                return(Task.CompletedTask);
            }

            // It's a bit of wasted IO to perform this check again, but non-symlinks shouldn't use this code
            if (!IsSymLink(result.FileName))
            {
                return(base.WriteFileAsync(context, result, range, rangeLength));
            }

            var response = context.HttpContext.Response;

            if (range != null)
            {
                return(SendFileAsync(
                           result.FileName,
                           response,
                           offset: range.From ?? 0L,
                           count: rangeLength));
            }

            return(SendFileAsync(
                       result.FileName,
                       response,
                       offset: 0,
                       count: null));
        }
 /// <summary>
 /// Write the contents of the fileStream to the response body.
 /// </summary>
 /// <param name="context">The <see cref="HttpContext"/>.</param>
 /// <param name="fileStream">The fileStream to write.</param>
 /// <param name="range">The <see cref="RangeItemHeaderValue"/>.</param>
 /// <param name="rangeLength">The range length.</param>
 /// <returns>The async task.</returns>
 protected static async Task WriteFileAsync(HttpContext context, Stream fileStream, RangeItemHeaderValue?range, long rangeLength)
 {
     await FileResultHelper.WriteFileAsync(context, fileStream, range, rangeLength);
 }
Exemple #12
0
 protected override Task ExecuteCoreAsync(HttpContext context, RangeItemHeaderValue?range, long rangeLength)
 {
     return(FileResultHelper.WriteFileAsync(context, FileStream, range, rangeLength));
 }
        internal static int GetRangeItemLength(string?input, int startIndex, out RangeItemHeaderValue?parsedValue)
        {
            Debug.Assert(startIndex >= 0);

            // This parser parses number ranges: e.g. '1-2', '1-', '-2'.

            parsedValue = null;

            if (string.IsNullOrEmpty(input) || (startIndex >= input.Length))
            {
                return(0);
            }

            // Caller must remove leading whitespace. If not, we'll return 0.
            int current = startIndex;

            // Try parse the first value of a value pair.
            int fromStartIndex = current;
            int fromLength     = HttpRuleParser.GetNumberLength(input, current, false);

            if (fromLength > HttpRuleParser.MaxInt64Digits)
            {
                return(0);
            }

            current = current + fromLength;
            current = current + HttpRuleParser.GetWhitespaceLength(input, current);

            // After the first value, the '-' character must follow.
            if ((current == input.Length) || (input[current] != '-'))
            {
                // We need a '-' character otherwise this can't be a valid range.
                return(0);
            }

            current++; // skip the '-' character
            current = current + HttpRuleParser.GetWhitespaceLength(input, current);

            int toStartIndex = current;
            int toLength     = 0;

            // If we didn't reach the end of the string, try parse the second value of the range.
            if (current < input.Length)
            {
                toLength = HttpRuleParser.GetNumberLength(input, current, false);

                if (toLength > HttpRuleParser.MaxInt64Digits)
                {
                    return(0);
                }

                current = current + toLength;
                current = current + HttpRuleParser.GetWhitespaceLength(input, current);
            }

            if ((fromLength == 0) && (toLength == 0))
            {
                return(0); // At least one value must be provided in order to be a valid range.
            }

            // Try convert first value to int64
            long from = 0;

            if ((fromLength > 0) && !HeaderUtilities.TryParseInt64(input, fromStartIndex, fromLength, out from))
            {
                return(0);
            }

            // Try convert second value to int64
            long to = 0;

            if ((toLength > 0) && !HeaderUtilities.TryParseInt64(input, toStartIndex, toLength, out to))
            {
                return(0);
            }

            // 'from' must not be greater than 'to'
            if ((fromLength > 0) && (toLength > 0) && (from > to))
            {
                return(0);
            }

            parsedValue = new RangeItemHeaderValue((fromLength == 0 ? (long?)null : (long?)from),
                                                   (toLength == 0 ? (long?)null : (long?)to));
            return(current - startIndex);
        }
Exemple #14
0
        internal static async Task WriteFileAsync(HttpContext context, Stream fileStream, RangeItemHeaderValue?range, long rangeLength)
        {
            const int BufferSize   = 64 * 1024;
            var       outputStream = context.Response.Body;

            using (fileStream)
            {
                try
                {
                    if (range == null)
                    {
                        await StreamCopyOperation.CopyToAsync(fileStream, outputStream, count : null, bufferSize : 64 * 1024, cancel : context.RequestAborted);
                    }
                    else
                    {
                        fileStream.Seek(range.From !.Value, SeekOrigin.Begin);
                        await StreamCopyOperation.CopyToAsync(fileStream, outputStream, rangeLength, BufferSize, context.RequestAborted);
                    }
                }
                catch (OperationCanceledException)
                {
                    // Don't throw this exception, it's most likely caused by the client disconnecting.
                    // However, if it was cancelled for any other reason we need to prevent empty responses.
                    context.Abort();
                }
            }
        }
Exemple #15
0
    internal static async Task WriteFileAsync(HttpContext context, ReadOnlyMemory <byte> buffer, RangeItemHeaderValue?range, long rangeLength)
    {
        var outputStream = context.Response.Body;

        try
        {
            if (range is null)
            {
                await outputStream.WriteAsync(buffer, context.RequestAborted);
            }
            else
            {
                var from   = 0;
                var length = 0;

                checked
                {
                    // Overflow should throw
                    from   = (int)range.From !.Value;
                    length = (int)rangeLength;
                }

                await outputStream.WriteAsync(buffer.Slice(from, length), context.RequestAborted);
            }
        }
        catch (OperationCanceledException)
        {
            // Don't throw this exception, it's most likely caused by the client disconnecting.
            // However, if it was cancelled for any other reason we need to prevent empty responses.
            context.Abort();
        }
    }
        /// <inheritdoc/>
        protected virtual Task WriteFileAsync(ActionContext context, VirtualFileResult result, IFileInfo fileInfo, RangeItemHeaderValue?range, long rangeLength)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }

            return(WriteFileAsyncInternal(context.HttpContext, fileInfo, range, rangeLength, Logger));
        }
Exemple #17
0
 protected abstract Task ExecuteCoreAsync(HttpContext httpContext, RangeItemHeaderValue?range, long rangeLength);
        /// <inheritdoc/>
        protected virtual Task WriteFileAsync(ActionContext context, VirtualFileResult result, IFileInfo fileInfo, RangeItemHeaderValue?range, long rangeLength)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (result == null)
            {
                throw new ArgumentNullException(nameof(result));
            }

            if (range != null && rangeLength == 0)
            {
                return(Task.CompletedTask);
            }

            var response = context.HttpContext.Response;

            if (range != null)
            {
                Logger.WritingRangeToBody();
            }

            if (range != null)
            {
                return(response.SendFileAsync(fileInfo,
                                              offset: range.From ?? 0L,
                                              count: rangeLength));
            }

            return(response.SendFileAsync(fileInfo,
                                          offset: 0,
                                          count: null));
        }