C# 具有多个范围的HTTP请求
如果我想部分下载一个文件并在请求头中定义一个范围,我会 响应正文中请求文件的字节流 但如果我像下面那样指定多个范围,我总是为每个定义的范围获得一个额外的值 响应主体中损坏的响应头(它描述请求的范围) 下载的文件C# 具有多个范围的HTTP请求,c#,.net,http,httpwebrequest,C#,.net,Http,Httpwebrequest,如果我想部分下载一个文件并在请求头中定义一个范围,我会 响应正文中请求文件的字节流 但如果我像下面那样指定多个范围,我总是为每个定义的范围获得一个额外的值 响应主体中损坏的响应头(它描述请求的范围) 下载的文件 static void Main(string[] args) { Console.Write("Please enter target File: "); string Target = Console.ReadLine(); string Source =
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中所示的请求:
http://img197.imageshack.us/img197/8199/requesty.png
响应正文应仅包含文件的字节流,但在每个定义范围的开头还包含不需要的响应标头:
是否可以避免正文中的附加响应标头而不单独请求每个范围
或
是否有一种内置方式来过滤额外的响应头,其大小可能因HTTP服务器而异?否,这就是HTTP/1.1中多个范围的工作方式。请参阅。感谢您的帮助,如上面链接中所述,这是最理想的选择 http响应具有多个范围的请求的方式 所以 是否有可能避免正文中的附加响应标题,而不使用 分别请求每个范围 =>没有 是否有一种内置方式来过滤额外的响应头,其大小为 可能因HTTP服务器而异 =>我不知道,但是 也许你们中的一些人可以仔细看看下面的代码块 从文件数据中筛选标题:
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:;
}
}
}
}
public void DoDownload(范围[]范围)
{
HttpWebRequest请求=(HttpWebRequest)WebRequest.Create(m_源代码);
request.Credentials=CredentialCache.DefaultCredentials;
foreach(范围中的范围r)
{
请求.添加范围(r.From,r.To);
}
HttpWebResponse=(HttpWebResponse)request.GetResponse();
字符串边界=”;
Match m=Regex.Match(response.ContentType,@“^.*边界=(?.*)$”;
如果(m.成功)
{
边界=m组[“边界”]值;
}
其他的
{
抛出新的InvalidDataException(“无效数据包数据:未找到边界规范”);
}
使用(Stream source=response.GetResponseStream())
{
使用(FileStream target=File.Open(m_TargetFile,FileMode.OpenOrCreate,FileAccess.Write,FileShare.ReadWrite))
{
//有效载荷缓冲器
字节[]缓冲区=新字节[4096];
//当前范围标头的缓冲区
字节[]头=新字节[200];
//x字节后的下一个标头
int-NextHeader=0;
//标题中的当前位置[]
int HeaderPosition=0;
//缓冲区中的当前位置[]
int BufferPosition=0;
//留下数据继续
int bytestoproced=0;
//不带范围标头写入的总数据
长TotalBytesWrited=0;
//上次写入目标文件的数据计数
int字节数=0;
//已处理标头数据的大小
int HeaderSize=0;
//从ResponseStream读取的上次数据计数
int字节读取=0;
而((BytesRead=source.Read(buffer,0,buffer.Length))>0)
{
缓冲位置=0;
BytesToProceed=字节读取;
HeaderSize=0;
while(BytesToProceed>0)
{
如果(NextHeader==0)
{
对于(;HeaderPositionHeaderPosition&&BufferPosition=4&&
标题[标题位置-3]==0x0d&&
标题[标题位置-2]==0x0a&&
标题[标题位置-1]==0x0d&&
标题[标题位置]==0x0a)
{
string RangeHeader=Encoding.ASCII.GetString(头,0,头位置+1);
匹配mm=正则表达式匹配(RangeHeader,
@“^\r\n(--)?“+boundary+@”。*?(?\d+)\s*-\s*(?\d+/*\r\n\r\n”,RegexOptions.Singleline);
如果(mm.成功)
{
int RangeStart=Convert.ToInt32(mm.Groups[“from”].Value);
int RangeEnd=Convert.ToInt32(mm.Groups[“到”].Value);
NextHeader=(RangeEnd-RangeStart)+1;
搜索(RangeStart,SeekOrigin.Begin);
缓冲位置++;
BytesToProceed-=人头化+1;
头部位置=0;
HeaderSize=0;
打破
}
else{抛出新的InvalidDataException(“无效标头:缺少范围规范”);}
}
}
否则{转到新的;}
}
如果(NextHeader==0)
扔新的伤残者