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 } } }