Resuming downloading

2019-04-10 00:31发布

The idea is simple, i am creating a service where user can put the direct link of a file that is being hosted on another website and my program will open a stream to that remote server and start reading the file in bytes and then return each readed byte to the user.

so far i managed to get that working and here is my code

    public void Index()
    {
        //Create a stream for the file
        Stream stream = null;

        //This controls how many bytes to read at a time and send to the client
        int bytesToRead = 10000; //10000

        // Buffer to read bytes in chunk size specified above
        byte[] buffer = new Byte[bytesToRead];

        // The number of bytes read
        try
        {
            //Create a WebRequest to get the file
            HttpWebRequest fileReq = (HttpWebRequest)HttpWebRequest.Create("http://SOME-OTHER-SERVER.com/File.rar");


            //Create a response for this request
            HttpWebResponse fileResp = (HttpWebResponse)fileReq.GetResponse();


            if (fileReq.ContentLength > 0)
                fileResp.ContentLength = fileReq.ContentLength;

            //Get the Stream returned from the response
            stream = fileResp.GetResponseStream();

            // prepare the response to the client. resp is the client Response
            var resp = HttpContext.Response;

            //Indicate the type of data being sent
            resp.ContentType = "application/octet-stream";

            //Name the file 
            resp.AddHeader("Content-Disposition", "attachment; filename=\"" + "fle.rar" + "\"");
            resp.AddHeader("Content-Length", (fileResp.ContentLength).ToString());

            int length;
            do
            {
                // Verify that the client is connected.
                if (resp.IsClientConnected)
                {
                    // Read data into the buffer.
                    length = stream.Read(buffer, 0, bytesToRead);

                    // and write it out to the response's output stream
                    resp.OutputStream.Write(buffer, 0, length);

                    // Flush the data
                    resp.Flush();

                    //Clear the buffer
                    buffer = new Byte[bytesToRead];
                }
                else
                {
                    // cancel the download if client has disconnected
                    length = -1;
                }
            } while (length > 0); //Repeat until no data is read
        }
        finally
        {
            if (stream != null)
            {
                //Close the input stream
                stream.Close();
            }
        }
    }

When i go to my page it downloads perfectly but the problem is if i stopped the download it won't resume again.

I searched for that issue and figured out that there is a header "Accept-Ranges" that must be defined in the connection in order to support resume.

so i added that header but didn't work.

1条回答
劫难
2楼-- · 2019-04-10 00:57

Handling Range Requests is a little bit more complicated than that. In general you need to handle Range and If-Range headers in request and serve proper 206 Partial Content responses with Content-Range, Date and ETag or Content-Location headers.

The article Range Requests in ASP.NET MVC – RangeFileResult describes in details how to create an ASP.NET MVC ActionResult with Range Request support.

In your case you will also have to check if the other side (the one for which you use fileReq) support Range Request. If yes than you can request just the needed part (and preferably cache it somewhere locally), but if not than you need to get the entire file and seek to proper locations (in that situation you defintely want to have a local caching scenario).

查看更多
登录 后发表回答