Exemplo n.º 1
0
        public ByteRangeStream(Stream innerStream, RangeItemHeaderValue range)
            : base(innerStream)
        {
            if (range == null)
            {
                throw new ArgumentNullException("range");
            }
            if (!innerStream.CanSeek)
            {
                throw new ArgumentException("innerStream");
            }
            if (innerStream.Length < 1)
            {
                throw new ArgumentOutOfRangeException("innerStream");
            }
            if (range.From.HasValue && range.From.Value > innerStream.Length)
            {
                throw new ArgumentOutOfRangeException("range");
            }

            // Ranges are inclusive so 0-9 means the first 10 bytes
            long maxLength = innerStream.Length - 1;
            long upperbounds;
            if (range.To.HasValue)
            {
                if (range.From.HasValue)
                {
                    // e.g bytes=0-499 (the first 500 bytes offsets 0-499)
                    upperbounds = Math.Min(innerStream.Position + range.To.Value, maxLength);
                    _lowerbounds = innerStream.Position + range.From.Value;
                }
                else
                {
                    // e.g bytes=-500 (the final 500 bytes)
                    upperbounds = Math.Min(innerStream.Position + range.To.Value, maxLength);
                    _lowerbounds = innerStream.Position;
                }
            }
            else
            {
                if (range.From.HasValue)
                {
                    // e.g bytes=500- (from byte offset 500 and up)
                    upperbounds = maxLength;
                    _lowerbounds = innerStream.Position + range.From.Value;
                }
                else
                {
                    // e.g. bytes=- (invalid so will never get here)
                    upperbounds = maxLength;
                    _lowerbounds = innerStream.Position;
                }
            }

            _totalCount = upperbounds - _lowerbounds + 1;

            ContentRange = new RangeItemHeaderValue(
                range.From ?? 0,
                range.To ?? innerStream.Length - innerStream.Position);
        }
Exemplo n.º 2
0
        protected virtual 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);
            }

            var response = context.HttpContext.Response;

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

            var sendFile = response.HttpContext.Features.Get <IHttpSendFileFeature>();

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

                return(sendFile.SendFileAsync(
                           result.FileName,
                           offset: 0,
                           count: null,
                           cancellation: default(CancellationToken)));
            }

            return(WriteFileAsync(context.HttpContext, GetFileStream(result.FileName), range, rangeLength));
        }
Exemplo n.º 3
0
        protected static async Task WriteFileAsync(HttpContext context, Stream fileStream, RangeItemHeaderValue range, long rangeLength)
        {
            var outputStream = context.Response.Body;

            using (fileStream)
            {
                try
                {
                    if (range == null)
                    {
                        await StreamCopyOperation.CopyToAsync(fileStream, outputStream, count : null, bufferSize : BufferSize, 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();
                }
            }
        }
Exemplo n.º 4
0
        public IHttpActionResult Get([FromUri] string filename)
        {
            string path = HttpContext.Current.Server.MapPath("~/" + filename);

            if (!File.Exists(path))
            {
                return(NotFound());
            }

            try
            {
                MemoryStream responseStream = new MemoryStream();
                Stream       fileStream     = File.Open(path, FileMode.Open);
                bool         fullContent    = true;
                if (this.Request.Headers.Range != null)
                {
                    fullContent = false;

                    // Currently we only support a single range.
                    RangeItemHeaderValue range = this.Request.Headers.Range.Ranges.First();


                    // From specified, so seek to the requested position.
                    if (range.From != null)
                    {
                        fileStream.Seek(range.From.Value, SeekOrigin.Begin);

                        // In this case, actually the complete file will be returned.
                        if (range.From == 0 && (range.To == null || range.To >= fileStream.Length))
                        {
                            fileStream.CopyTo(responseStream);
                            fullContent = true;
                        }
                    }
                    if (range.To != null)
                    {
                        // 10-20, return the range.
                        if (range.From != null)
                        {
                            long?  rangeLength = range.To - range.From;
                            int    length      = (int)Math.Min(rangeLength.Value, fileStream.Length - range.From.Value);
                            byte[] buffer      = new byte[length];
                            fileStream.Read(buffer, 0, length);
                            responseStream.Write(buffer, 0, length);
                        }
                        // -20, return the bytes from beginning to the specified value.
                        else
                        {
                            int    length = (int)Math.Min(range.To.Value, fileStream.Length);
                            byte[] buffer = new byte[length];
                            fileStream.Read(buffer, 0, length);
                            responseStream.Write(buffer, 0, length);
                        }
                    }
                    // No Range.To
                    else
                    {
                        // 10-, return from the specified value to the end of file.
                        if (range.From != null)
                        {
                            if (range.From < fileStream.Length)
                            {
                                int    length = (int)(fileStream.Length - range.From.Value);
                                byte[] buffer = new byte[length];
                                fileStream.Read(buffer, 0, length);
                                responseStream.Write(buffer, 0, length);
                            }
                        }
                    }
                }
                // No Range header. Return the complete file.
                else
                {
                    fileStream.CopyTo(responseStream);
                }
                fileStream.Close();
                responseStream.Position = 0;

                HttpResponseMessage response = new HttpResponseMessage();
                response.StatusCode = fullContent ? HttpStatusCode.OK : HttpStatusCode.PartialContent;
                response.Content    = new StreamContent(responseStream);
                return(Ok(response));
            }
            catch (IOException)
            {
                return(InternalServerError());
            }
            catch (Exception)
            {
                return(InternalServerError());
            }
        }
Exemplo n.º 5
0
        private static void CheckInvalidGetRangeItemListLength(string input, int startIndex)
        {
            List <RangeItemHeaderValue> ranges = new List <RangeItemHeaderValue>();

            Assert.Equal(0, RangeItemHeaderValue.GetRangeItemListLength(input, startIndex, ranges));
        }
        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);
            }

            return(WriteFileAsync(context.HttpContext, result.FileStream, range, rangeLength));
        }
Exemplo n.º 7
0
        public HttpResponseMessage getCustomDict()
        {
            HttpResponseMessage response = new HttpResponseMessage();
            string   filepath            = AppDomain.CurrentDomain.BaseDirectory;
            string   filename            = filepath + "\\Dicts\\updict.dic";
            FileInfo fileinfo            = new FileInfo(filename);

            if (fileinfo == null)
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }
            string etag = string.Format("\"{0}\"", GetMD5.GetMD5HashFromFile(filename));
            var    tag  = Request.Headers.IfNoneMatch.FirstOrDefault();

            if (Request.Headers.IfModifiedSince.HasValue && tag != null && tag.Tag == etag)
            {
                response.StatusCode = HttpStatusCode.NotModified;
            }
            else
            {
                FileStream   fs             = fileinfo.OpenRead();
                MemoryStream responseStream = new MemoryStream();
                bool         fullContent    = true;

                if (this.Request.Headers.Range != null)
                {
                    fullContent = false;
                    RangeItemHeaderValue range = this.Request.Headers.Range.Ranges.First();
                    if (range.From != null)
                    {
                        fs.Seek(range.From.Value, SeekOrigin.Begin);
                        if (range.From == 0 && (range.To == null || range.To >= fs.Length))
                        {
                            fs.CopyTo(responseStream);
                            fullContent = true;
                        }
                    }
                    if (range.To != null)
                    {
                        if (range.From != null)
                        {
                            long?  rangeLength = range.To - range.From;
                            int    length      = (int)Math.Min(rangeLength.Value, fs.Length - range.From.Value);
                            byte[] buffer      = new byte[length];
                            fs.Read(buffer, 0, length);
                            responseStream.Write(buffer, 0, length);
                        }
                        else
                        {
                            int    length = (int)Math.Min(range.To.Value, fs.Length);
                            byte[] buffer = new byte[length];
                            fs.Read(buffer, 0, length);
                            responseStream.Write(buffer, 0, length);
                        }
                    }
                    else
                    {
                        if (range.From != null)
                        {
                            if (range.From < fs.Length)
                            {
                                int    length = (int)(fs.Length - range.From.Value);
                                byte[] buffer = new byte[length];
                                fs.Read(buffer, 0, length);
                                responseStream.Write(buffer, 0, length);
                            }
                        }
                    }
                }
                else
                {
                    fs.CopyTo(responseStream);
                }
                fs.Close();
                responseStream.Position               = 0;
                response.StatusCode                   = fullContent ? HttpStatusCode.OK : HttpStatusCode.PartialContent;
                response.Content                      = new StreamContent(responseStream);
                response.Headers.ETag                 = new EntityTagHeaderValue(etag);
                response.Headers.CacheControl         = new CacheControlHeaderValue();
                response.Headers.CacheControl.Public  = true;
                response.Headers.CacheControl.MaxAge  = TimeSpan.FromHours(24);
                response.Content.Headers.Expires      = DateTimeOffset.Now.AddDays(1);
                response.Content.Headers.LastModified = fileinfo.LastWriteTime;
            }
            return(response);
        }
Exemplo n.º 8
0
        private async Task SendResponseAsync(PreconditionState state, HttpContext context, EntityTagHeaderValue etag, DateTimeOffset lastModified, string contentType, IFileInfo fileInfo)
        {
            switch (state)
            {
            //304 Not Modified
            case PreconditionState.NotModified:
            {
                context.SetResponseHeaders(304, etag, lastModified, contentType,
                                           fileInfo.Length);
                break;
            }

            //416 Precondition Failded
            case PreconditionState.PreconditionFailed:
            {
                context.SetResponseHeaders(412, etag, lastModified, contentType, fileInfo.Length);
                break;
            }

            case PreconditionState.Unspecified:
            case PreconditionState.ShouldProcess:
            {
                //200 OK
                if (context.UseMethods("HEAD"))
                {
                    context.SetResponseHeaders(200, etag, lastModified, contentType, fileInfo.Length);
                    return;
                }

                IEnumerable <RangeItemHeaderValue> ranges;
                if (context.IsRangeRequest() && this.TryGetRanges(context, lastModified, etag, fileInfo.Length, out ranges))
                {
                    RangeItemHeaderValue range = ranges.FirstOrDefault();
                    //416
                    if (null == range)
                    {
                        context.SetResponseHeaders(416, etag, lastModified, contentType, fileInfo.Length);
                        return;
                    }
                    else
                    {
                        //206 Partial Content
                        context.SetResponseHeaders(206, etag, lastModified, contentType, fileInfo.Length, range);
                        context.Response.GetTypedHeaders().ContentRange = new ContentRangeHeaderValue(range.From.Value, range.To.Value, fileInfo.Length);
                        using (var stream = fileInfo.CreateReadStream())
                        {
                            stream.Seek(range.From.Value, SeekOrigin.Begin);
                            await StreamCopyOperation.CopyToAsync(stream, context.Response.Body, range.To - range.From + 1, context.RequestAborted);
                        }
                        return;
                    }
                }
                //200 OK
                context.SetResponseHeaders(200, etag, lastModified, contentType, fileInfo.Length);
                using (Stream stream = fileInfo.CreateReadStream())
                {
                    await StreamCopyOperation.CopyToAsync(stream, context.Response.Body, fileInfo.Length, context.RequestAborted);
                }
                break;
            }
            }
        }
Exemplo n.º 9
0
        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;
            var physicalPath = fileInfo.PhysicalPath;

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

            var sendFile = response.HttpContext.Features.Get <IHttpSendFileFeature>();

            if (sendFile != null && !string.IsNullOrEmpty(physicalPath))
            {
                if (range != null)
                {
                    return(sendFile.SendFileAsync(
                               physicalPath,
                               offset: range.From ?? 0L,
                               count: rangeLength,
                               cancellation: default(CancellationToken)));
                }

                return(sendFile.SendFileAsync(
                           physicalPath,
                           offset: 0,
                           count: null,
                           cancellation: default(CancellationToken)));
            }

            return(WriteFileAsync(context.HttpContext, GetFileStream(fileInfo), range, rangeLength));
        }
Exemplo n.º 10
0
        public HttpResponseMessage Download(string fileName)
        {
            var    fileuploadPath = @"D:\TestZip";
            string path           = Path.Combine(fileuploadPath, fileName);

            if (!File.Exists(path))
            {
                throw new HttpResponseException(HttpStatusCode.NotFound);
            }

            //try
            //{
            bool         fullContent    = true;
            MemoryStream responseStream = new MemoryStream();
            Stream       fileStream     = File.Open(path, FileMode.Open);

            if (this.Request.Headers.Range != null)
            {
                fullContent = false;

                // Currently we only support a single range.
                RangeItemHeaderValue range = this.Request.Headers.Range.Ranges.First();


                // From specified, so seek to the requested position.
                if (range.From != null)
                {
                    fileStream.Seek(range.From.Value, SeekOrigin.Begin);

                    // In this case, actually the complete file will be returned.
                    if (range.From == 0 && (range.To == null || range.To >= fileStream.Length))
                    {
                        fileStream.CopyTo(responseStream);
                        fullContent = true;
                    }
                }
                if (range.To != null)
                {
                    // 10-20, return the range.
                    if (range.From != null)
                    {
                        long?  rangeLength = range.To - range.From;
                        int    length      = (int)Math.Min(rangeLength.Value, fileStream.Length - range.From.Value);
                        byte[] buffer      = new byte[length];
                        fileStream.Read(buffer, 0, length);
                        responseStream.Write(buffer, 0, length);
                    }
                    // -20, return the bytes from beginning to the specified value.
                    else
                    {
                        int    length = (int)Math.Min(range.To.Value, fileStream.Length);
                        byte[] buffer = new byte[length];
                        fileStream.Read(buffer, 0, length);
                        responseStream.Write(buffer, 0, length);
                    }
                }
                // No Range.To
                else
                {
                    // 10-, return from the specified value to the end of file.
                    if (range.From != null)
                    {
                        if (range.From < fileStream.Length)
                        {
                            int    length = (int)(fileStream.Length - range.From.Value);
                            byte[] buffer = new byte[length];
                            fileStream.Read(buffer, 0, length);
                            responseStream.Write(buffer, 0, length);
                        }
                    }
                }
            }
            // No Range header. Return the complete file.
            else
            {
                fileStream.CopyTo(responseStream);
            }
            fileStream.Close();
            responseStream.Position = 0;

            HttpResponseMessage response = new HttpResponseMessage();

            response.StatusCode = fullContent ? HttpStatusCode.OK : HttpStatusCode.PartialContent;
            response.Content    = new StreamContent(responseStream);
            return(response);
            //}
            //catch (IOException)
            //{
            //    throw new HttpResponseException(HttpStatusCode.InternalServerError);
            //}
        }
Exemplo n.º 11
0
        public void Ctor_ThrowsOnNullInnerStream()
        {
            var range = new RangeItemHeaderValue(0, 10);

            Assert.ThrowsArgumentNull(() => new ByteRangeStream(innerStream: null, range: range), "innerStream");
        }
Exemplo n.º 12
0
        public async Task <HttpResponseMessage> StreamingResource([FromUri] string id)
        {
            using (var db = new OnlineMusicEntities())
            {
                var resource = (from r in db.Resources
                                where r.Id == id
                                select r).FirstOrDefault();
                if (resource == null)
                {
                    return(Request.CreateErrorResponse(HttpStatusCode.NotFound, "Không tìm thấy resource"));
                }

                stream = await services.Stream(id);

                var mediaType = "image/jpg";
                if (resource.Type == (int)ResourceTypeManager.Audio)
                {
                    mediaType = "audio/mpeg";
                }
                else if (resource.Type == (int)ResourceTypeManager.Video)
                {
                    mediaType = "video/mp4";
                }

                RangeHeaderValue range = Request.Headers.Range;

                if (range != null)
                {
                    try
                    {
                        // Convert percent to bytes
                        if (range.Unit == "percent" && range.Ranges.Count > 0)
                        {
                            Request.Headers.Range.Unit = "bytes";
                            var  value = range.Ranges.First();
                            long?from  = value.From != null ? stream.Length * value.From / 100 : null;
                            long?to    = value.To != null ? stream.Length * value.To / 100 : null;
                            RangeItemHeaderValue newValue = new RangeItemHeaderValue(from, to);
                            Request.Headers.Range.Ranges.Remove(value);
                            Request.Headers.Range.Ranges.Add(newValue);
                        }
                        HttpResponseMessage partialResponse = Request.CreateResponse(HttpStatusCode.PartialContent);
                        partialResponse.Content = new ByteRangeStreamContent(stream, Request.Headers.Range, mediaType);
                        return(partialResponse);
                    }
                    catch (Exception ex)
                    {
                        return(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex.Message));
                    }
                }
                else
                {
                    HttpContent content;
                    if (resource.Type == (int)ResourceTypeManager.Video)
                    {
                        content = new PushStreamContent((Func <Stream, HttpContent, TransportContext, Task>)WriteToStream, new MediaTypeHeaderValue(mediaType));
                    }
                    else
                    {
                        content = new StreamContent(stream);
                    }
                    var response = Request.CreateResponse(HttpStatusCode.OK);
                    response.Content = content;
                    response.Content.Headers.ContentLength = stream.Length;
                    response.Content.Headers.ContentType   = new MediaTypeHeaderValue(mediaType);
                    return(response);
                }
            }
        }
Exemplo n.º 13
0
    internal static int GetRangeItemLength(StringSegment input, int startIndex, out RangeItemHeaderValue?parsedValue)
    {
        Contract.Requires(startIndex >= 0);

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

        parsedValue = null;

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

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

        // Try parse the first value of a value pair.
        var fromStartIndex = current;
        var 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);

        var toStartIndex = current;
        var 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.TryParseNonNegativeInt64(input.Subsegment(fromStartIndex, fromLength), out from))
        {
            return(0);
        }

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

        if ((toLength > 0) && !HeaderUtilities.TryParseNonNegativeInt64(input.Subsegment(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);
    }
        /// <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));
        }