123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- using System.Net.Http.Headers;
- namespace Bmp.Core.Common.Net
- {
- public class SeekableHttpStream : Stream
- {
- private readonly string _url;
- private long _length;
- private long _position = 0;
- private HttpClient? _httpClient;
- private HttpResponseMessage? _httpResponseMessage;
- private HttpContent? _httpContent;
- private Stream? _underlyingHttpStream;
- public SeekableHttpStream(string url)
- {
- _url = url;
- Init();
- }
- private void Init()
- {
- DeInit();
- _httpClient = new HttpClient();
- var req = new HttpRequestMessage(HttpMethod.Get, _url);
- if (_position != 0)
- {
- req.Headers.Range ??= new();
- req.Headers.Range!.Ranges.Add(new RangeItemHeaderValue(_position, null));
- }
- _httpResponseMessage = _httpClient.Send(req, HttpCompletionOption.ResponseHeadersRead);
- _httpResponseMessage!.EnsureSuccessStatusCode();
- _httpContent = _httpResponseMessage.Content;
- if (_httpContent.Headers.ContentLength.HasValue) _length = _position + _httpContent.Headers.ContentLength.Value;
- _underlyingHttpStream = _httpContent.ReadAsStream();
- }
- private void DeInit()
- {
- _underlyingHttpStream?.Close();
- _httpContent?.Dispose();
- _httpClient?.Dispose();
- }
- public override void Close()
- {
- base.Close();
- DeInit();
- }
- public override int Read(byte[] buffer, int offset, int count)
- {
- var read = _underlyingHttpStream!.Read(buffer, offset, count);
- _position += read;
- return read;
- }
- public override long Seek(long offset, SeekOrigin origin)
- {
- switch (origin)
- {
- case SeekOrigin.Begin:
- _position = offset;
- Init();
- break;
- case SeekOrigin.Current:
- _position += offset;
- Init();
- break;
- case SeekOrigin.End:
- _position = _length + offset;
- Init();
- break;
- default: throw new ArgumentOutOfRangeException(nameof(offset));
- }
- return _position;
- }
- //-----------------------------------------------
- public override void Flush()
- {
- throw new NotSupportedException();
- }
- public override void SetLength(long value)
- {
- throw new NotSupportedException();
- }
- public override void Write(byte[] buffer, int offset, int count)
- {
- throw new NotSupportedException();
- }
- public override bool CanRead => true;
- public override bool CanSeek => true;
- public override bool CanWrite => false;
- public override long Length => _length;
- public override long Position { get => _position; set => Seek(value, SeekOrigin.Begin); }
- }
- }
|