public async Task BeginRead()
            {
                int NrRead;

                try
                {
                    do
                    {
                        while (this.BytesLeft > 0)
                        {
                            NrRead = await this.f.ReadAsync(this.Buffer, 0, (int)Math.Min(this.BlockSize, this.BytesLeft));

                            if (NrRead <= 0)
                            {
                                await this.Dispose();

                                return;
                            }
                            else
                            {
                                await this.Response.Write(this.Buffer, 0, NrRead);

                                this.BytesLeft -= NrRead;
                            }
                        }

                        if (this.Next != null)
                        {
                            long First;

                            if (this.Next.First.HasValue)
                            {
                                First = this.Next.First.Value;
                            }
                            else
                            {
                                First = this.TotalLength - this.Next.Last.Value;
                            }

                            this.f.Position = First;
                            this.BytesLeft  = this.Next.GetIntervalLength(this.TotalLength);

                            await Response.WriteLine();

                            await Response.WriteLine("--" + this.Boundary);

                            await Response.WriteLine("Content-Type: " + this.ContentType);

                            await Response.WriteLine("Content-Range: " + ContentByteRangeInterval.ContentRangeToString(First, First + this.BytesLeft - 1, this.TotalLength));

                            await Response.WriteLine();

                            this.Next = this.Next.Next;
                        }
                    }while (this.BytesLeft > 0);

                    if (!string.IsNullOrEmpty(this.Boundary))
                    {
                        await Response.WriteLine();

                        await Response.WriteLine("--" + this.Boundary + "--");
                    }

                    Variables Session;

                    if (!(this.Request is null) &&
                        this.Request.Header.Method == "GET" &&
                        !((Session = this.Request.Session) is null) &&
                        Session.ContainsVariable(" LastPost "))
                    {
                        Session.Remove(" LastPost ");
                        Session.Remove(" LastPostResource ");
                        Session.Remove(" LastPostReferer ");
                    }

                    await this.Dispose();
                }
                catch (Exception ex)
                {
                    try
                    {
                        if (!this.Response.HeaderSent)
                        {
                            await this.Response.SendResponse(ex);
                        }
                        else
                        {
                            await this.Response.Flush();
                        }

                        this.Response.Dispose();
                        this.Response = null;

                        await this.Dispose();
                    }
                    catch (Exception)
                    {
                        // Ignore
                    }
                }
            }
        /// <summary>
        /// Executes the ranged GET method on the resource.
        /// </summary>
        /// <param name="Request">HTTP Request</param>
        /// <param name="Response">HTTP Response</param>
        /// <param name="FirstInterval">First byte range interval.</param>
        /// <exception cref="HttpException">If an error occurred when processing the method.</exception>
        public async Task GET(HttpRequest Request, HttpResponse Response, ByteRangeInterval FirstInterval)
        {
            string FullPath = this.GetFullPath(Request);

            if (File.Exists(FullPath))
            {
                HttpRequestHeader Header       = Request.Header;
                DateTime          LastModified = File.GetLastWriteTime(FullPath).ToUniversalTime();
                DateTimeOffset?   Limit;
                CacheRec          Rec;

                if (Header.IfRange != null && (Limit = Header.IfRange.Timestamp).HasValue &&
                    !LessOrEqual(LastModified, Limit.Value.ToUniversalTime()))
                {
                    Response.StatusCode = 200;
                    await this.GET(Request, Response);                        // No ranged request.

                    return;
                }

                Rec = this.CheckCacheHeaders(FullPath, LastModified, Request);

                string ContentType = InternetContent.GetContentType(Path.GetExtension(FullPath));
                Stream f           = CheckAcceptable(Request, Response, ref ContentType, out bool Dynamic, FullPath, Request.Header.Resource);
                Rec.IsDynamic = Dynamic;

                if (Response.ResponseSent)
                {
                    return;
                }

                ReadProgress Progress = new ReadProgress()
                {
                    Response = Response,
                    Request  = Request,
                    f        = f ?? File.Open(FullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
                };

                ByteRangeInterval Interval = FirstInterval;
                Progress.TotalLength = Progress.f.Length;

                long i = 0;
                long j;
                long First;

                if (FirstInterval.First.HasValue)
                {
                    First = FirstInterval.First.Value;
                }
                else
                {
                    First = Progress.TotalLength - FirstInterval.Last.Value;
                }

                Progress.f.Position = First;
                Progress.BytesLeft  = Interval.GetIntervalLength(Progress.TotalLength);
                Progress.Next       = Interval.Next;

                while (Interval != null)
                {
                    j = Interval.GetIntervalLength(Progress.TotalLength);
                    if (j > i)
                    {
                        i = j;
                    }

                    Interval = Interval.Next;
                }

                Progress.BlockSize = (int)Math.Min(BufferSize, i);
                Progress.Buffer    = new byte[Progress.BlockSize];

                if (FirstInterval.Next is null)
                {
                    Progress.Boundary    = null;
                    Progress.ContentType = null;

                    Response.ContentType   = ContentType;
                    Response.ContentLength = FirstInterval.GetIntervalLength(Progress.f.Length);
                    Response.SetHeader("Content-Range", ContentByteRangeInterval.ContentRangeToString(First, First + Progress.BytesLeft - 1, Progress.TotalLength));
                }
                else
                {
                    Progress.Boundary    = Guid.NewGuid().ToString().Replace("-", string.Empty);
                    Progress.ContentType = ContentType;

                    Response.ContentType = "multipart/byteranges; boundary=" + Progress.Boundary;
                    // chunked transfer encoding will be used
                }

                if (!Rec.IsDynamic)
                {
                    Response.SetHeader("ETag", Rec.ETag);
                    Response.SetHeader("Last-Modified", CommonTypes.EncodeRfc822(LastModified));
                }

                if (Response.OnlyHeader || Progress.BytesLeft == 0)
                {
                    await Response.SendResponse();

                    await Progress.Dispose();
                }
                else
                {
                    if (FirstInterval.Next != null)
                    {
                        await Response.WriteLine();

                        await Response.WriteLine("--" + Progress.Boundary);

                        await Response.WriteLine("Content-Type: " + Progress.ContentType);

                        await Response.WriteLine("Content-Range: " + ContentByteRangeInterval.ContentRangeToString(First, First + Progress.BytesLeft - 1, Progress.TotalLength));

                        await Response.WriteLine();
                    }

                    Task _ = Progress.BeginRead();
                }
            }
            else
            {
                await this.RaiseFileNotFound(FullPath, Request, Response);
            }
        }
            public async Task BeginRead()
            {
                int NrRead;

                try
                {
                    do
                    {
                        while (this.BytesLeft > 0)
                        {
                            NrRead = await this.f.ReadAsync(this.Buffer, 0, (int)Math.Min(this.BlockSize, this.BytesLeft));

                            if (NrRead <= 0)
                            {
                                this.Dispose();
                                return;
                            }
                            else
                            {
                                this.Response.Write(this.Buffer, 0, NrRead);
                                this.BytesLeft -= NrRead;
                            }
                        }

                        if (this.Next != null)
                        {
                            long First;

                            if (this.Next.First.HasValue)
                            {
                                First = this.Next.First.Value;
                            }
                            else
                            {
                                First = this.TotalLength - this.Next.Last.Value;
                            }

                            this.f.Position = First;
                            this.BytesLeft  = this.Next.GetIntervalLength(this.TotalLength);

                            Response.WriteLine();
                            Response.WriteLine("--" + this.Boundary);
                            Response.WriteLine("Content-Type: " + this.ContentType);
                            Response.WriteLine("Content-Range: " + ContentByteRangeInterval.ContentRangeToString(First, First + this.BytesLeft - 1, this.TotalLength));
                            Response.WriteLine();

                            this.Next = this.Next.Next;
                        }
                    }while (this.BytesLeft > 0);

                    if (!string.IsNullOrEmpty(this.Boundary))
                    {
                        Response.WriteLine();
                        Response.WriteLine("--" + this.Boundary + "--");
                    }

                    this.Dispose();
                }
                catch (Exception ex)
                {
                    try
                    {
                        if (!this.Response.HeaderSent)
                        {
                            this.Response.SendResponse(ex);
                        }
                        else
                        {
                            this.Response.Flush();
                        }

                        this.Response.Dispose();
                        this.Response = null;

                        this.Dispose();
                    }
                    catch (Exception)
                    {
                        // Ignore
                    }
                }
            }