Using .NET to Post a file to Server HttpWebRequest or WebClient
Asked Answered
A

2

8

Okay so here is the deal. As the question states, I'm trying to POST a file to a webserver and am having a few issues.

I've tried posting this same file to the same webserver using Curl.exe and have had no issues. I've posted the flags I used with curl just incase they might point out any potential reasons why I'm having trouble with the .NET classes.

curl.exe --user "myUser:myPass" --header "Content-Type: application/gzip"  
--data-binary "@filename.txt.gz" --cookie "data=service; data-ver=2; date=20100212;  
time=0900; location=1234" --output "out.txt" --dump-header "header.txt"  
http://mysite/receive

I'm trying to use a .NET class like WebClient or HttpWebRequest to do the same thing. Here is a sample of the code I've tried. With the WebClient I get a 505 HTTP Version Not Supported error and with the HttpWebRequest I get a 501 Not Implemented.

When trying it with a WebClient:

public void sendFileClient(string path){
    string url = "http://mysite/receive";  
    WebClient wc = new WebClient();  
    string USERNAME = "myUser";  
    string PSSWD = "myPass";  

    NetworkCredential creds = new NetworkCredential(USERNAME, PSSWD);  
    wc.Credentials = creds;  
    wc.Headers.Set(HttpRequestHeader.ContentType, "application/gzip");  
    wc.Headers.Set("Cookie", "location=1234; date=20100226; time=1630; data=service; data-ver=2");  

    wc.UploadFile(url, "POST", path);
}

And while using a HttpRequest:

public Stream sendFile(string path)
{
    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://myserver/receive");  
    string USERNAME = "myUser";    
    string PSSWD = "myPass";  
    NetworkCredential creds = new NetworkCredential(USERNAME, PSSWD);  
    request.Credentials = creds;  
    request.Method = "POST";  
    request.ContentType = "application/gzip";    
    request.Headers.Set("Cookie", "location=1234; date=20100226; time=1630; data=service; data-ver=2");  
    FileInfo fInfo = new FileInfo(path);  
    long numBytes = fInfo.Length;  
    FileStream fStream = new FileStream(path, FileMode.Open, FileAccess.Read);  
    BinaryReader br = new BinaryReader(fStream);  
    byte[] data = br.ReadBytes((int)numBytes);  
    br.Close();  
    fStream.Close();  
    fStream.Dispose();  
    Stream wrStream = request.GetRequestStream();  
    BinaryWriter bw = new BinaryWriter(wrStream);  
    bw.Write(data);  
    bw.Close();  
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();  
    return response.GetResponseStream();  
}
Arms answered 2/3, 2010 at 4:5 Comment(1)
Use a debugging http proxy to see exactly what the difference is between the two calls over the wire. Try Charles (charlesproxy.com) or Fiddler (fiddler2.com/fiddler2).Tamaru
P
10

First, use something like fiddler and inspect the requests and responses to see what differs between curl and System.Net.WebClient.

Also, you can try (although inspecting with the debugging proxy should allow you to pinpoint the difference):

Use the credential cache to set your credentials for basic authentication:

var cc= new CredentialCache();
cc.Add(new Uri(url),
                  "Basic", 
                  new NetworkCredential("USERNAME", "PASSWORD"));
wc.Credentials = cc;

Set a user agent header:

string _UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)";
wc.Headers.Add(HttpRequestHeader.UserAgent, _UserAgent);

Change the protocol version on the WebRequest:

reqeust.KeepAlive = false;
request.ProtocolVersion=HttpVersion.Version10;
Pelham answered 2/3, 2010 at 4:31 Comment(2)
The "Change the protocol version on the WebRequest" did the trick!Arms
Similar problem: Adding a user agent header fixed it for me.Ehudd
T
1

There might be another 2 reasons when a 501 accord.

----------1---------

when the postdate contain some Chinese Chracter or some other character. e.g.

postDate = "type=user&username=计算机学院&password=123&Submit=+登录+"

in order post the right message,you may also add following 2 line;

Request.SendChunked = true;
Request.TransferEncoding = "GB2312";

this also lead to a 501.

in that occasion,you can delete the 2 line,and modify postDate like so.

postDate = "type=user&username=%BC%C6%CB%E3%BB%FA%D1%A7%D4%BA&password=123&Submit=+%C8%B7%C8%CF+"

maybe this is a solution to modify the postDate,however i havn't test yet.

string str = Encoding.GetEncoding("gb2312").GetString(tmpBytes);

----------2---------

if Response.StatusCode == HttpStatusCode.Redirect Redirect is equals to 302. following line is a must:

Request.AllowAutoRedirect = false;
Tm answered 23/4, 2011 at 2:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.