Sending a file to a remote server (C#.NET) using HTTP POST

Posted on 2009-02-24
Last Modified: 2013-12-17
I need help with sending a file to a remote server using a POST request (along with other either POST and/or GET data).
I have researched this an the only thing that does both (GET and POST at the same time) I have found is cURL.
I have used cURL in the past with PHP and it has been very easy to implement. With .NET (using cURL .NET library however I'm running into an issue where I am unable to "attach" the file to the HTTP POST request. If there are alternate methods for sending data (including a file) to a remote server (where I have a receiving scipt expecting a POST request) without using cURL please let me know.

Below I have a working code that takes a variable named "fields" containing a series of key=value pairs connected with ampersand (same as URI query string): key1=value1&key2=value2&...
The problem I am running into here is how to get a file across using this method in .NET. Again if there are other (better?) ways of accomplishing this please do let me know.

On the other end (the remote server) I have a script that processes the received date (as if it was submitted using a standard HTML form via HTTP POST) and the additional variables (submitted as the HTTP GET variables).
If I just use a file name for the CURLOPT_POSTFIELDS option as below I only get the file name as the variable - no file though:

easy.SetOpt(CURLoption.CURLOPT_POSTFIELDS, "myFile=myfile.txt");

If I add the contents as in the script below, I see the variable but no file or file name. So seems like I am missing on how the file stream needs to be formatted or something.

On the receiving end the script generates also a log file with all headers and data it receives along with attempting to receive the submitted file for confirmation purposes.

Any help would be greatly appreciated!
// This is in C#.NET - which works except for the file transfer part

string url = "";

string fileLocation = "C:\\myUploadFolder\\myFile.txt";

string fields = "?key1=value1&key2=value2";


System.IO.StreamReader sr = new System.IO.StreamReader(fileLocation);

fileContents = sr.ReadToEnd();



CURLcode context = Curl.GlobalInit((int)CURLinitFlag.CURL_GLOBAL_ALL);

Easy easy = new Easy();

easy.SetOpt(CURLoption.CURLOPT_URL, url);

easy.SetOpt(CURLoption.CURLOPT_PORT, 443);

easy.SetOpt(CURLoption.CURLOPT_POST, 1);

easy.SetOpt(CURLoption.CURLOPT_POSTFIELDS, "myFile=" + fileContents);

easy.SetOpt(CURLoption.CURLOPT_URL, url + "?" + fields);




// This is how I have used it in PHP - which works including the file transfer part

$url = "";

$fileLocation = "C:\myUploadFolder\myFile.txt";

$fields = "?key1=value1&key2=value2";


$ch = curl_init();

curl_setopt($ch, CURLOPT_URL,$url);

curl_setopt($ch, CURLOPT_POST, 1);

curl_setopt($ch, CURLOPT_POSTFIELDS, array("myFile"=>"@$fileLocation");

curl_setopt($ch, CURLOPT_URL, $url . $fields);

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);

$postResult = curl_exec($ch);


print $postResult;

Open in new window

Question by:ttepandi
    LVL 15

    Expert Comment

    Do you need all of that extra stuff? has a class called WebClient.

    System.Net.WebClient wc = new System.Net.WebClient;
    wc.UploadFile("", "POST", "C:\myUploadFolder\myFile.txt")

    Author Comment

    That's crazy - I looked at this and completely dismissed it. No, I do not need all of that extra stuff, just passing GET variables and sending a file.

    I have tested this out now and here is where it stands.
    The receiving script is being called but it does not see the request as a POST request.  Do I need to add some special headers? I attempted MSDN suggested headers but no luck.

    wc.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");

    LVL 15

    Expert Comment

    Yeah, I forgot to include the header you need.

    WebClient webClient = new WebClient();                  
    webClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded");

    For a GET, you can do something like this.
    string postData = String.Format("value1={1}&value2={2}", variable1, variable2);
    byte[] response = webClient.UploadData("the url", "GET", Encoding.ASCII.GetBytes(postData));
    LVL 15

    Accepted Solution

    Actually, after looking in to the WebClient a little more, it looks like it doesn't support multipart/form-data, which is what you need to send variables along with a file.  But, you can use HttpWebRequest.  After digging around some I found this function.  Enjoy.
    private void UploadFilesToRemoteUrl(string url, string[] files, string
    logpath, NameValueCollection nvc)
    long length = 0;
    string boundary = "----------------------------" +
    HttpWebRequest httpWebRequest2 = (HttpWebRequest)WebRequest.Create(url);
    httpWebRequest2.ContentType = "multipart/form-data; boundary=" +
    httpWebRequest2.Method = "POST";
    httpWebRequest2.KeepAlive = true;
    httpWebRequest2.Credentials =
    Stream memStream = new System.IO.MemoryStream();
    byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
    boundary + "\r\n");
    string formdataTemplate = "\r\n--" + boundary +
    "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";
    foreach(string key in nvc.Keys)
    string formitem = string.Format(formdataTemplate, key, nvc[key]);
    byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
    memStream.Write(formitembytes, 0, formitembytes.Length);
    memStream.Write(boundarybytes,0,boundarybytes.Leng th);
    string headerTemplate = "Content-Disposition: form-data; name=\"{0}\";
    filename=\"{1}\"\r\n Content-Type: application/octet-stream\r\n\r\n";
    for(int i=0;i<files.Length;i++)
    string header = string.Format(headerTemplate,"file"+i,files[i]);
    byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
    FileStream fileStream = new FileStream(files[i], FileMode.Open,
    byte[] buffer = new byte[1024];
    int bytesRead = 0;
    while ( (bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0 )
    memStream.Write(buffer, 0, bytesRead);
    memStream.Write(boundarybytes,0,boundarybytes.Leng th);
    httpWebRequest2.ContentLength = memStream.Length;
    Stream requestStream = httpWebRequest2.GetRequestStream();
    memStream.Position = 0;
    byte[] tempBuffer = new byte[memStream.Length];
    requestStream.Write(tempBuffer,0,tempBuffer.Length );
    WebResponse webResponse2 = httpWebRequest2.GetResponse();
    Stream stream2 = webResponse2.GetResponseStream();
    StreamReader reader2 = new StreamReader(stream2);
    httpWebRequest2 = null;
    webResponse2 = null;

    Open in new window


    Author Comment

    OK. Thank you very much!
    I have tried out this code now and I was not able to get this to work. I have made sure that there are no access issues but still for some reason the filestream is not reaching the receiving script. The receiving PHP script does get the POST variables now but still now file.

    I have replaced the "Receiving" script with one in C# on the same machine where the "Posting" script resides; same domain, same folder for testing purposes to eliminate any cross-domain or access rights issues but still no dice. I am getting now "Object reference not set to an instance of an object" error. The file is not reaching the receiving script and I cannot figure out why. There's got to be something I am doing wrong on the sending side.

    Getting access to the GET variables is not a problem no matter what method I use. I found that I can also just append the GET variables to the end of the URL when using the WebClient method="POST" route for example.

    I will post my sample code on using the above if you don't mind looking at it.

    Author Comment

    Turns out I was not paying attention. There might be a more straightforward way of figuring this out, but I was specifying the filename reference incorrectly: it should have been Request.Files["file0"].FileName

    using the ploadFilesToRemoteUrl method it sets the filenames in the headers as "file" + i, where i is the index and starts at 0.

    Below is a working code sample using the UploadFilesToRemoteUrl method specified above.

    Hope this helps someone searching to upload files to a remote script.

    Thank you for your help!
    protected void Page_Load(object sender, EventArgs e)
        string url = "";
        string fileName = "MyTestFile.csv";
        string path = System.IO.Path.GetFullPath("C:\\test\\filesToSend\\");
        NameValueCollection myCol = new NameValueCollection();
        myCol.Add("fileName", fileName);
        string[] files = new string[1];
        files[0] = path + fileName;
        UploadFilesToRemoteUrl(url, files, "", myCol);
    // postReceive.aspx.cs
    protected void Page_Load(object sender, EventArgs e)
        string savePath = "C:\\test\\filesReceived\\";
        fileName = System.IO.Path.GetFileName(Request.Files["file0"].FileName);
        Request.Files["file0"].SaveAs(savePath + "MyNew_" + fileName);

    Open in new window


    Author Closing Comment

    Thank you for your help!

    Write Comment

    Please enter a first name

    Please enter a last name

    We will never share this with anyone.

    Featured Post

    How your wiki can always stay up-to-date

    Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
    - Increase transparency
    - Onboard new hires faster
    - Access from mobile/offline

    In my previous article ( we saw the basics of serialization and how types/objects can be serialized to Binary format. In this blog we wi…
    In my previous two articles we discussed Binary Serialization ( and XML Serialization ( In this article we will try to know more about SOAP (Simple Object Acces…
    This video is in connection to the article "The case of a missing mobile phone (". It will help one to understand clearly the steps to track a lost android phone.
    Sending a Secure fax is easy with eFax Corporate ( First, Just open a new email message.  In the To field, type your recipient's fax number You can even send a secure international fax — just include t…

    760 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    13 Experts available now in Live!

    Get 1:1 Help Now