This stream does not support seek operations. HttpWebResponse

15,594

Solution 1

If the server supports this you have to send the Range Http header with your request using the AddRange method:

request.AddRange(1024);

This will instruct the server to start sending the file after the 1st kilobyte. Then just read the response stream as normal.

To test if a server supports resuming you can send a HEAD request and test if it sends the Accept-Ranges: bytes header.

Solution 2

How about an HTTPRangeStream class?

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;

namespace Ionic.Kewl
{
    public class HTTPRangeStream : Stream
    {
        private string url;
        private long length;
        private long position;
        private long totalBytesRead;
        private int totalReads;

        public HTTPRangeStream(string URL)
        {
            url = URL;
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
            HttpWebResponse result = (HttpWebResponse)request.GetResponse();
            length = result.ContentLength;
        }

        public long TotalBytesRead    { get { return totalBytesRead; } }
        public long TotalReads        { get { return totalReads; } }
        public override bool CanRead  { get { return true; } }
        public override bool CanSeek  { get { return true; } }
        public override bool CanWrite { get { return false; } }
        public override long Length   { get { return length; } }

        public override bool CanTimeout
        {
            get
            {
                return base.CanTimeout;
            }
        }


        public override long Position
        {
            get
            {
                return position;
            }
            set
            {
                if (value < 0) throw new ArgumentException();
                position = value;
            }
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            switch (origin)
            {
                case SeekOrigin.Begin:
                    position = offset;
                    break;
                case SeekOrigin.Current:
                    position += offset;
                    break;
                case SeekOrigin.End:
                    position = Length + offset;
                    break;
                default:
                    break;
            }
            return Position;
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
            request.AddRange(Convert.ToInt32(position), Convert.ToInt32(position) + count);
            HttpWebResponse result = (HttpWebResponse)request.GetResponse();
            using (Stream stream = result.GetResponseStream())
            {
                stream.Read(buffer, offset, count);
                stream.Close();
            }
            totalBytesRead += count;
            totalReads++;
            Position += count;
            return count;
        }


        public override void Write(byte[] buffer, int offset, int count)
        {
            throw new NotSupportedException();
        }

        public override void SetLength(long value)
        {
            throw new NotSupportedException();
        }
        public override void Flush()
        {
            throw new NotSupportedException();
        }

    }
}
Share:
15,594
Admin
Author by

Admin

Updated on June 06, 2022

Comments

  • Admin
    Admin almost 2 years

    I'm making a program which downloads files over http.

    I've got it downloading, however I want to be able to pause the downloads, close the program and resume them again at a later date.

    I know the location i'm downloading them from supports this.

    I'm downloading the file through HttpWebResponse and reading the response into a Stream using GetResponseStream.

    When i close the app and restart it, I'm stuck as to how resume the download. I've tried doing a seek on the stream but it states its not supported.

    What would be the best way to do this?

  • Jon Skeet
    Jon Skeet over 14 years
    Do you want to add a link to the MSDN docs? msdn.microsoft.com/en-us/library/…
  • Smith
    Smith over 12 years
    Does this class work even if the server does not accept resuming?
  • Cheeso
    Cheeso over 12 years
    I don't know what "resuming" is. HTTP 1.1 defines a Range header, which this class relies on. if the server does HTTP 1.1, then it does Range, and can be contacted by this class.
  • Smith
    Smith over 12 years
    by resuming i meant range header, thanks for the clarification