带有进度跟踪的C#HttpWebRequest表单Post(用于上载可能较大的文件)

带有进度跟踪的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

我正在编写一个winforms应用程序,它将文件发布到web应用程序(不是我的)。就发布文件本身而言,我的工作进展顺利,我的问题是,我想提供一些指示,说明我发送请求的进展情况

下面的代码是我尝试使用BeginGetResponse来达到这一目的的代码——这就是我发现请求仍然阻塞的地方

有什么建议可以让我开始寻找吗

    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