问题描述
如果我想部分下载的文件,并定义一个范围请求头,我得到字节流中的反应体所需的文件的
if I want to partially download a file and define a single range in the request Header, I getthe 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 additionalresponse header (wich describes the requested range) within the response body that corruptsthe 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 supposedway http responds to a request with multiple ranges.
左右....
是否有可能避免在体内的附加响应头未经量程分别要求每个?
Is it possible to avoid the additional response header in the body withoutrequesting each Range separately?
=>无。
是否有一个内置的方式来筛选附加响应头,其大小可以根据HTTP的服务器上的变化?
Is there a build-in way to filter the additional response header, whose sizecould 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 wichfilters 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 regardscap_Chap
这篇关于HTTP请求与多个范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!