带有进度跟踪的C#HttpWebRequest表单Post(用于上载可能较大的文件)
我正在编写一个winforms应用程序,它将文件发布到web应用程序(不是我的)。就发布文件本身而言,我的工作进展顺利,我的问题是,我想提供一些指示,说明我发送请求的进展情况 下面的代码是我尝试使用BeginGetResponse来达到这一目的的代码——这就是我发现请求仍然阻塞的地方 有什么建议可以让我开始寻找吗带有进度跟踪的C#HttpWebRequest表单Post(用于上载可能较大的文件),c#,.net,winforms,post,httpwebrequest,C#,.net,Winforms,Post,Httpwebrequest,我正在编写一个winforms应用程序,它将文件发布到web应用程序(不是我的)。就发布文件本身而言,我的工作进展顺利,我的问题是,我想提供一些指示,说明我发送请求的进展情况 下面的代码是我尝试使用BeginGetResponse来达到这一目的的代码——这就是我发现请求仍然阻塞的地方 有什么建议可以让我开始寻找吗 public void Dummy() { Dictionary<string, string> fields = new Dictiona
public void Dummy()
{
Dictionary<string, string> fields = new Dictionary<string, string>();
fields.Add("key", "something");
HttpWebRequest hr = WebRequest.Create("http://somesite.com/api/something.xml") as HttpWebRequest;
string bound = "----------------------------" + DateTime.Now.Ticks.ToString("x");
hr.ContentType = "multipart/form-data; boundary=" + bound;
hr.Method = "POST";
hr.KeepAlive = true;
hr.Credentials = CredentialCache.DefaultCredentials;
byte[] boundBytes = Encoding.ASCII.GetBytes("\r\n--" + bound + "\r\n");
string formDataTemplate = "\r\n--" + bound + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";
Stream s = hr.GetRequestStream();
foreach (string key in fields.Keys)
{
byte[] formItemBytes = Encoding.UTF8.GetBytes(
string.Format(formDataTemplate, key, fields[key]));
s.Write(formItemBytes, 0, formItemBytes.Length);
}
s.Write(boundBytes, 0, boundBytes.Length);
string headerTemplate =
"Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n Content-Type: application/octet-stream\r\n\r\n";
List<string> files = new List<string> { Server.MapPath("/Images/Phillip.jpg") };
foreach (string f in files)
{
byte[] headerBytes = Encoding.UTF8.GetBytes(
String.Format(headerTemplate, "image", f));
s.Write(headerBytes, 0, headerBytes.Length);
FileStream fs = new FileStream(f, FileMode.Open, FileAccess.Read);
int bytesRead = 0;
byte[] buffer = new byte[1024];
while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) != 0)
{
s.Write(buffer, 0, buffer.Length);
}
s.Write(boundBytes, 0, boundBytes.Length);
fs.Close();
}
s.Close();
string respString ="";
hr.BeginGetResponse((IAsyncResult res) =>
{
WebResponse resp = ((HttpWebRequest)res.AsyncState).EndGetResponse(res);
StreamReader respReader = new StreamReader(resp.GetResponseStream());
respString = respReader.ReadToEnd();
resp.Close();
resp = null;
}, hr);
while (!hr.HaveResponse)
{
Debug.Write("hiya bob!");
Thread.Sleep(150);
}
Debug.Write(respString);
hr = null;
}
public void Dummy()
{
字典字段=新字典();
字段。添加(“键”、“某物”);
HttpWebRequest hr=WebRequest.Create(“http://somesite.com/api/something.xml)作为HttpWebRequest;
字符串绑定=“------------------------------------”+DateTime.Now.Ticks.ToString(“x”);
hr.ContentType=“多部分/表单数据;边界=“+绑定;
hr.Method=“POST”;
hr.KeepAlive=true;
hr.Credentials=CredentialCache.DefaultCredentials;
byte[]boundBytes=Encoding.ASCII.GetBytes(“\r\n--”+bound+”\r\n”);
字符串formDataTemplate=“\r\n--”+bound+“\r\n内容处理:表单数据;名称=\“{0}\”;\r\n\r\n{1}”;
streams=hr.GetRequestStream();
foreach(字段中的字符串键。键)
{
byte[]formItemBytes=Encoding.UTF8.GetBytes(
格式(formDataTemplate,key,fields[key]);
s、 写入(formItemBytes,0,formItemBytes.Length);
}
s、 写入(boundBytes,0,boundBytes.Length);
字符串头模板=
“内容处置:表单数据;名称=\”{0}\“文件名=\”{1}\“\r\n内容类型:应用程序/八位字节流\r\n\r\n”;
列表文件=新列表{Server.MapPath(“/Images/Phillip.jpg”)};
foreach(文件中的字符串f)
{
字节[]头字节=Encoding.UTF8.GetBytes(
格式(headerTemplate,“image”,f);
s、 写入(headerBytes,0,headerBytes.Length);
FileStream fs=newfilestream(f,FileMode.Open,FileAccess.Read);
int字节读取=0;
字节[]缓冲区=新字节[1024];
while((bytesRead=fs.Read(buffer,0,buffer.Length))!=0)
{
s、 写入(缓冲区,0,缓冲区长度);
}
s、 写入(boundBytes,0,boundBytes.Length);
fs.Close();
}
s、 Close();
字符串respString=“”;
hr.BeginGetResponse((IAsyncResult res)=>
{
WebResponse resp=((HttpWebRequest)res.AsyncState).EndGetResponse(res);
StreamReader respreder=新的StreamReader(resp.GetResponseStream());
respString=respreder.ReadToEnd();
分别关闭();
resp=null;
},hr);
而(!hr.HaveResponse)
{
Debug.Write(“你好,鲍勃!”);
睡眠(150);
}
Debug.Write(respString);
hr=null;
}
好的,算了。如果设置了ContentLength属性,则HttpWebRequest对象将在调用GetRequestStream()时直接将其ResponseStream连接到网络套接字。这样,您就可以通过直接写入此流来跟踪进度
伪代码:
Request r = CreateWebRequest(Url)
r.ContentLength = CalculateRequestLength(fields, files)
Stream requestStream = r.GetRequestStream()
while(moreData)
{
requestStream.write(someData);
UpdateProgress();
}
r.GetResponse();
工作代码:
public void Dummy()
{
Dictionary<string, string> fields = new Dictionary<string, string>();
fields.Add("key", "something");
HttpWebRequest hr = WebRequest.Create("http://imgur.com/api/upload.xml") as HttpWebRequest;
string bound = "----------------------------" + DateTime.Now.Ticks.ToString("x");
hr.ContentType = "multipart/form-data; boundary=" + bound;
hr.Method = "POST";
hr.KeepAlive = true;
hr.Credentials = CredentialCache.DefaultCredentials;
byte[] boundBytes = Encoding.ASCII.GetBytes("\r\n--" + bound + "\r\n");
string formDataTemplate = "\r\n--" + bound + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";
//add fields + a boundary
MemoryStream fieldData = new MemoryStream();
foreach (string key in fields.Keys)
{
byte[] formItemBytes = Encoding.UTF8.GetBytes(
string.Format(formDataTemplate, key, fields[key]));
fieldData.Write(formItemBytes, 0, formItemBytes.Length);
}
fieldData.Write(boundBytes, 0, boundBytes.Length);
//calculate the total length we expect to send
List<string> files = new List<string> { Server.MapPath("/Images/Phillip.jpg") };
string headerTemplate =
"Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n Content-Type: application/octet-stream\r\n\r\n";
long fileBytes = 0;
foreach (string f in files)
{
byte[] headerBytes = Encoding.UTF8.GetBytes(
String.Format(headerTemplate, "image", f));
FileStream fs = new FileStream(f, FileMode.Open, FileAccess.Read);
fileBytes += headerBytes.Length;
fileBytes += fs.Length;
fileBytes += boundBytes.Length;
fs.Close();
}
hr.ContentLength = fieldData.Length + fileBytes;
Stream s = hr.GetRequestStream();
//write the fields to the request stream
Debug.WriteLine("sending field data");
fieldData.WriteTo(s);
//write the files to the request stream
Debug.WriteLine("sending file data");
foreach (string f in files)
{
byte[] headerBytes = Encoding.UTF8.GetBytes(
String.Format(headerTemplate, "image", f));
s.Write(headerBytes, 0, headerBytes.Length);
FileStream fs = new FileStream(f, FileMode.Open, FileAccess.Read);
int bytesRead = 0;
long bytesSoFar = 0;
byte[] buffer = new byte[10240];
while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) != 0)
{
bytesSoFar += bytesRead;
s.Write(buffer, 0, bytesRead);
Debug.WriteLine(String.Format("sending file data {0:0.000}%", (bytesSoFar * 100.0f) / fs.Length));
}
s.Write(boundBytes, 0, boundBytes.Length);
fs.Close();
}
s.Close();
GetResponseDel d = new GetResponseDel(GetResponse);
ResponseData data = new ResponseData { del = d };
d.BeginInvoke(hr, EndGetResponse, data);
while (!hr.HaveResponse)
{
Debug.Write("waiting for response" + "\n");
Thread.Sleep(150);
}
Debug.Write(data.responseString);
hr = null;
}
delegate WebResponse GetResponseDel(HttpWebRequest hr);
private WebResponse GetResponse(HttpWebRequest hr)
{
return hr.GetResponse();
}
class ResponseData
{
public GetResponseDel del { get; set; }
public string responseString { get; set; }
}
private void EndGetResponse(IAsyncResult res)
{
ResponseData data = (ResponseData)res.AsyncState;
GetResponseDel d = data.del;
WebResponse r = d.EndInvoke(res);
data.responseString = new StreamReader(r.GetResponseStream()).ReadToEnd();
}
public void Dummy()
{
字典字段=新字典();
字段。添加(“键”、“某物”);
HttpWebRequest hr=WebRequest.Create(“http://imgur.com/api/upload.xml)作为HttpWebRequest;
字符串绑定=“------------------------------------”+DateTime.Now.Ticks.ToString(“x”);
hr.ContentType=“多部分/表单数据;边界=“+绑定;
hr.Method=“POST”;
hr.KeepAlive=true;
hr.Credentials=CredentialCache.DefaultCredentials;
byte[]boundBytes=Encoding.ASCII.GetBytes(“\r\n--”+bound+”\r\n”);
字符串formDataTemplate=“\r\n--”+bound+“\r\n内容处理:表单数据;名称=\“{0}\”;\r\n\r\n{1}”;
//添加字段+边界
MemoryStream fieldData=新的MemoryStream();
foreach(字段中的字符串键。键)
{
byte[]formItemBytes=Encoding.UTF8.GetBytes(
格式(formDataTemplate,key,fields[key]);
fieldData.Write(formItemBytes,0,formItemBytes.Length);
}
fieldData.Write(boundBytes,0,boundBytes.Length);
//计算我们希望发送的总长度
列表文件=新列表{Server.MapPath(“/Images/Phillip.jpg”)};
串头模板=
“内容处置:表单数据;名称=\”{0}\“文件名=\”{1}\“\r\n内容类型:应用程序/八位字节流\r\n\r\n”;
长fileBytes=0;
foreach(文件中的字符串f)
{
字节[]头字节=Encoding.UTF8.GetBytes(
格式(headerTemplate,“image”,f);
FileStream fs=newfilestream(f,FileMode.Open,FileAccess.Read);
fileBytes+=headerBytes.Length;
fileBytes+=fs.Length;
fileBytes+=boundBytes.Length;
fs.Close();
}
hr.ContentLength=fieldData.Length+fileBytes;
streams=hr.GetRequestStream();
//将字段写入请求流
Debug.WriteLine(“发送字段数据”);
fieldData.WriteTo(多个);
//将文件写入请求流
WriteLine(“发送文件数据”);
foreach(文件中的字符串f)
{
字节[]头字节=Encoding.UTF8.GetBytes(
格式(headerTemplate,“image”,f);
s、 写入(headerBytes,0,headerBytes.Length);
FileStream fs=newfilestream(f,FileMode.Open,FileAccess.Read);
int字节读取=0;
long bytesSoFar=0;
字节[]缓冲区=新字节[10240];
而((bytesRead=fs.Read)(缓冲区,0