HTTP请求与多个范围 [英] HTTP Request with multiple Ranges

查看:130
本文介绍了HTTP请求与多个范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我想部分下载的文件,并定义一个范围请求头,我得到 字节流中的反应体所需的文件的

if I want to partially download a file and define a single range in the request Header, I get the byte-stream of the requested file in the response body.

但是,如果我指定为以下多个范围,我总是为每个定义的范围的附加 响应头(至极说明了请求范围)响应主体的腐化之内 下载的文件。

But if i specify multiple ranges as below, I always get for each defined range an additional response header (wich describes the requested range) within the response body that corrupts the downloaded file.

static void Main(string[] args)
{

    Console.Write("Please enter target File: ");
    string Target = Console.ReadLine();
    string Source = @"http://mozilla-mirror.3347.voxcdn.com/pub/mozilla.org/firefox/releases/3.6/win32/de/Firefox%20Setup%203.6.exe";

    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Source);
    request.Credentials = CredentialCache.DefaultCredentials;

    // define multiple Ranges
    request.AddRange(      0, 1000000);
    request.AddRange(1000000, 2000000);

    HttpWebResponse response = (HttpWebResponse)request.GetResponse();

    using (Stream source = response.GetResponseStream())
    {
        using (FileStream target = File.Open(Target, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
        {
            byte[] buffer = new byte[4096];
            int BytesRead = 0;
            int TotalBytesRead = 0;

            while((BytesRead = source.Read(buffer, 0, buffer.Length)) > 0) 
            {
                target.Write(buffer, 0, BytesRead);
                TotalBytesRead += BytesRead;

                Console.WriteLine("{0}", TotalBytesRead);
            }
        }
    }

    Console.WriteLine("Downloading Finished!");
    Console.ReadLine();
}

要求,如图Wireshark的:

Request as shown in Wireshark:

http://img197.imageshack.us/img197/8199/requesty.png

响应体应该只包含文件的字节流,而且还包含了不必要的响应头在每个定义范围的开头:

Response Body should only contain the Byte-Stream of the file, but additionally contains the unwanted Response-Header at the beginning of each defined Range:

是否有可能避免在身体的额外的响应头不要求每个范围分别?

Is it possible to avoid the additional response header in the body without requesting each Range separately?

有一个内置的方式来过滤额外的响应头,其大小可以根据HTTP的服务器上的变化?

Is there a build-in way to filter the additional response header, whose size could vary depending on the HTTP-Server?

推荐答案

感谢您的帮助,因为在它上面的链接描述的假想 方法HTTP响应与多个范围的请求。

thanks for your help, as described in the link above it is the supposed way http responds to a request with multiple ranges.

左右....

是否有可能避免在体内的附加响应头未经 量程分别要求每个?

Is it possible to avoid the additional response header in the body without requesting each Range separately?

=>无。

是否有一个内置的方式来筛选附加响应头,其大小 可以根据HTTP的服务器上的变化?

Is there a build-in way to filter the additional response header, whose size could vary depending on the HTTP-Server?

=>我不知道,但......

=> I don't know but ...

也许有些你可以有一个关键看code至极以下块 从文件中的数据过滤头:

maybe some of you could have a critical look at the following chunk of code wich filters the headers from the file data:

public void DoDownload(Range[] Ranges)
    {

        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(m_Source);
        request.Credentials = CredentialCache.DefaultCredentials;

        foreach (Range r in Ranges)
        {
            request.AddRange(r.From, r.To);
        }

        HttpWebResponse response = (HttpWebResponse)request.GetResponse();

        string boundary = "";
        Match m = Regex.Match(response.ContentType, @"^.*boundary=(?<boundary>.*)$");

        if (m.Success)
        {
            boundary = m.Groups["boundary"].Value;
        }
        else
        {
            throw new InvalidDataException("invalid packet data: no boundary specification found.");
        }


        using (Stream source = response.GetResponseStream())
        {
            using (FileStream target = File.Open(m_TargetFile, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
            {
                // buffer for payload
                byte[] buffer = new byte[4096];
                // buffer for current range header
                byte[] header = new byte[200];
                // next header after x bytes
                int NextHeader = 0;
                // current position in header[]
                int HeaderPosition = 0;
                // current position in buffer[]
                int BufferPosition = 0;
                // left data to proceed
                int BytesToProceed = 0;
                // total data written without range-headers
                long TotalBytesWritten = 0;
                // count of last data written to target file
                int BytesWritten = 0;
                // size of processed header data
                int HeaderSize = 0;
                // count of last data read from ResponseStream
                int BytesRead = 0;


                while ((BytesRead = source.Read(buffer, 0, buffer.Length)) > 0)
                {
                    BufferPosition = 0;
                    BytesToProceed = BytesRead;
                    HeaderSize = 0;

                    while (BytesToProceed > 0)
                    {
                        if (NextHeader == 0)
                        {
                            for (;HeaderPosition < header.Length; HeaderPosition++, BufferPosition++, HeaderSize++)
                            {
                                if (BytesToProceed > HeaderPosition && BufferPosition < BytesRead)
                                {
                                    header[HeaderPosition] = buffer[BufferPosition];

                                    if (HeaderPosition >= 4 &&
                                        header[HeaderPosition - 3] == 0x0d &&
                                        header[HeaderPosition - 2] == 0x0a &&
                                        header[HeaderPosition - 1] == 0x0d &&
                                        header[HeaderPosition] == 0x0a)
                                    {
                                        string RangeHeader = Encoding.ASCII.GetString(header, 0, HeaderPosition + 1);
                                        Match mm = Regex.Match(RangeHeader,
                                            @"^\r\n(--)?" + boundary + @".*?(?<from>\d+)\s*-\s*(?<to>\d+)/.*\r\n\r\n", RegexOptions.Singleline);

                                        if (mm.Success)
                                        {
                                            int RangeStart = Convert.ToInt32(mm.Groups["from"].Value);
                                            int RangeEnd = Convert.ToInt32(mm.Groups["to"].Value);

                                            NextHeader = (RangeEnd - RangeStart) + 1; 

                                            target.Seek(RangeStart, SeekOrigin.Begin);
                                            BufferPosition++;

                                            BytesToProceed -= HeaderSize + 1;

                                            HeaderPosition = 0;
                                            HeaderSize = 0;

                                            break;
                                        }
                                        else { throw new InvalidDataException("invalid header: missing range specification.");}
                                    }
                                }
                                else { goto READ_NEW; }
                            }

                            if (NextHeader == 0)
                                throw new InvalidDataException("invalid packet data: no range-header found.");
                        }

                        BytesWritten = (NextHeader > BytesToProceed) ? BytesToProceed : NextHeader;

                        target.Write(buffer, BufferPosition, BytesWritten);

                        BytesToProceed -= BytesWritten;
                        NextHeader -= BytesWritten;
                        BufferPosition += BytesWritten;

                        TotalBytesWritten += BytesWritten;
                    }

                READ_NEW:;
                }
            }
        }
    }

和可以给我一些提示,如果有一个又一个的/更好的方式来做到这一点。

and could give me some hints if there is a another/better way to do that.

最好的问候 cap_Chap

best regards cap_Chap

这篇关于HTTP请求与多个范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆