Link to home
Start Free TrialLog in
Avatar of ttepandi
ttepandi

asked on

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

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 http://curl.haxx.se/libcurl/dotnet/) 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 = "https://myreceivingservice.com/requestResponse.php";
string fileLocation = "C:\\myUploadFolder\\myFile.txt";
string fields = "?key1=value1&key2=value2";
 
System.IO.StreamReader sr = new System.IO.StreamReader(fileLocation);
fileContents = sr.ReadToEnd();
sr.Close();
 
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);
easy.SetOpt(CURLoption.CURLOPT_FOLLOWLOCATION, 1);
 
 
// This is how I have used it in PHP - which works including the file transfer part
$url = "https://myreceivingservice.com/requestResponse.php";
$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);
curl_close($ch);
print $postResult;

Open in new window

Avatar of aibusinesssolutions
aibusinesssolutions
Flag of United States of America image

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

System.Net.WebClient wc = new System.Net.WebClient;
wc.UploadFile("https://myreceivingservice.com/requestResponse.php", "POST", "C:\myUploadFolder\myFile.txt")
Avatar of ttepandi
ttepandi

ASKER

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;)");


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));
ASKER CERTIFIED SOLUTION
Avatar of aibusinesssolutions
aibusinesssolutions
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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.
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!
//postSend.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
    string url = "http://mydomain.com/postReceive.aspx";
    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

Thank you for your help!