c# multipart/form-data submit programmatically
So got an small problem. Im creating an small application to automate an form submission on one website. But the bad thing is that they are using multipart/form-data for that. There is no file uploading just some text fields for submission.
Of course doing it like this it fails.
string postData1 = "firstfield="+firststring+"secondfield="+secondstring;
So my question is how the hell post those form fields with multipart form?
Posting like arrays in php like this:
$postdata = array('firstfield' => $firststring, 'secondfield' => $secondstring);
works and passes the form but seems not working with c#
Any suggestions?
Data submission goes through 3 page ( basic screenscrape ) login/part1/part2
So far i can log in successfully and post part1 (uses normal application/x-www-form-urlencoded form )
But when ill try to post multipart form it fails and sends me back to part1. So maybe is my code wrong but here it is:
string password = "password";
string username = "username";
string link = "http://somelink.com/";
string text = "Blah Blah some text here";
string title = "Blah Blah";
string tags1 = title;
string summary = "Blah Blah summary";
string tags = tags1.Replace(" ", ",");
// Set cookie container
CookieContainer cookieJar = new CookieContainer();
string loginData = "username=" + username + "&password=" + password + "&processlogin=1&return=%2Fsubmit.php";
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create("http://loginlink.com/login.php");
myRequest.Method = "POST";
myRequest.ServicePoint.Expect100Continue = false;
myRequest.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.4) Gecko/20091016 Firefox/3.5.4 GTB6 (.NET CLR 3.5.30729)";
myRequest.Timeout = 10000;
myRequest.ContentType = "application/x-www-form-urlencoded";
myRequest.ContentLength = loginData.Length;
myRequest.CookieContainer = cookieJar;
myRequest.KeepAlive = true;
myRequest.AllowAutoRedirect = true;
//Write post data to stream
StreamWriter myWriter = new StreamWriter(myRequest.GetRequestStream());
myWriter.Write(loginData);
myWriter.Close();
// Get the response.
HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
// Open the stream using a StreamReader for easy access.
StreamReader myReader = new StreamReader(myResponse.GetResponseStream());
// Read the content.
string output = myReader.ReadToEnd();
// Clean up the streams and the response.
myReader.Close();
myResponse.Close();
Match matchkey = Regex.Match(output, "type=\"hidden\" name=\"randkey\" value=\"([^\"]+)\"", RegexOptions.IgnoreCase);
string key1 = matchkey.Groups[1].Value;
Match matchid = Regex.Match(output, "type=\"hidden\" name=\"id\" value=\"([^\"]+)\"", RegexOptions.IgnoreCase);
string id1 = matchid.Groups[1].Value;
string postData = "url=" + link + "&phase=1&randkey=" + key1 + "&id=" + id1;
HttpWebRequest myRequest2 = (HttpWebRequest)WebRequest.Create("http://submitpage1.com/submit.php");
myRequest2.Method = "POST";
myRequest2.ServicePoint.Expect100Continue = false;
myRequest2.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.4) Gecko/20091016 Firefox/3.5.4 GTB6 (.NET CLR 3.5.30729)";
myRequest2.Timeout = 10000;
myRequest2.ContentType = "application/x-www-form-urlencoded";
myRequest2.ContentLength = postData.Length;
myRequest2.CookieContainer = cookieJar;
myRequest2.KeepAlive = true;
myRequest2.AllowAutoRedirect = true;
//Write post data to stream
StreamWriter myWriter2 = new StreamWriter(myRequest2.GetRequestStream());
myWriter2.Write(postData);
myWriter2.Close();
// Get the response.
HttpWebResponse myResponse2 = (HttpWebResponse)myRequest2.GetResponse();
// Open the stream using a StreamReader for easy access.
StreamReader myReader2 = new StreamReader(myResponse2.GetResponseStream());
// Read the content.
string output1 = myReader2.ReadToEnd();
// Clean up the streams and the response.
myReader2.Close();
myResponse2.Close();
Match matchkey1 = Regex.Match(output1, "type=\"hidden\" name=\"randkey\" value=\"([^\"]+)\"", RegexOptions.IgnoreCase);
string key2 = matchkey1.Groups[1].Value;
Match matchid1 = Regex.Match(output1, "type=\"hidden\" name=\"randkey\" value=\"([^\"]+)\"", RegexOptions.IgnoreCase);
string id2 = matchid1.Groups[1].Value;
string boundary = "-----------------------------1721856231228";
// Build up the post
StringBuilder sb = new StringBuilder();
sb.Append("\r\n" + boundary + "\r\n");
sb.Append("Content-Disposition: form-data; name=\"title\"" + "\r\n");
sb.Append("\r\n");
sb.Append(title);
sb.Append("\r\n--" + boundary + "\r\n");
sb.Append("Content-Disposition: form-data; name=\"tags\"" + "\r\n");
sb.Append("\r\n");
sb.Append(tags);
sb.Append("\r\n--" + boundary + "\r\n");
sb.Append("Content-Disposition: form-data; name=\"bodytext\"" + "\r\n");
sb.Append("\r\n");
sb.Append(text);
sb.Append("\r\n--" + boundary + "\r\n");
sb.Append("Content-Disposition: form-data; name=\"summarycheckbox\"" + "\r\n");
sb.Append("\r\n");
sb.Append("on");
sb.Append("\r\n--" + boundary + "\r\n");
sb.Append("Content-Disposition: form-data; name=\"summarytext\"" + "\r\n");
sb.Append("\r\n");
sb.Append(summary);
sb.Append("\r\n--" + boundary + "\r\n");
sb.Append("Content-Disposition: form-data; name=\"remLen\"" + "\r\n");
sb.Append("\r\n");
sb.Append("125");
sb.Append("\r\n--" + boundary + "\r\n");
sb.Append("Content-Disposition: form-data; name=\"category\"开发者_JAVA技巧" + "\r\n");
sb.Append("\r\n");
sb.Append("1");
sb.Append("\r\n--" + boundary + "\r\n");
sb.Append("Content-Disposition: form-data; name=\"trackback\"" + "\r\n");
sb.Append("\r\n");
sb.Append("");
sb.Append("\r\n--" + boundary + "\r\n");
sb.Append("Content-Disposition: form-data; name=\"url\"" + "\r\n");
sb.Append("\r\n");
sb.Append(link);
sb.Append("\r\n--" + boundary + "\r\n");
sb.Append("Content-Disposition: form-data; name=\"phase\"" + "\r\n");
sb.Append("\r\n");
sb.Append("2");
sb.Append("\r\n--" + boundary + "\r\n");
sb.Append("Content-Disposition: form-data; name=\"randkey\"" + "\r\n");
sb.Append("\r\n");
sb.Append(key2);
sb.Append("\r\n--" + boundary + "\r\n");
sb.Append("Content-Disposition: form-data; name=\"id\"" + "\r\n");
sb.Append("\r\n");
sb.Append(id2);
sb.Append("\r\n--" + boundary + "--" + "\r\n");
string postData1 = sb.ToString();
HttpWebRequest myRequest3 = (HttpWebRequest)WebRequest.Create("http://submitpage2.com/submit.php");
myRequest3.Method = "POST";
myRequest3.UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.4) Gecko/20091016 Firefox/3.5.4 GTB6 (.NET CLR 3.5.30729)";
myRequest3.Timeout = 10000;
myRequest3.ServicePoint.Expect100Continue = false;
myRequest3.Referer = "http://bookmarkindo.com/submit.php";
myRequest3.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
myRequest3.ContentType = "multipart/form-data; boundary=" + boundary;
myRequest3.ContentLength = postData1.Length;
myRequest3.CookieContainer = cookieJar;
myRequest3.KeepAlive = true;
myRequest3.AllowAutoRedirect = true;
//Write out postdata
StreamWriter myWriter3 = new StreamWriter(myRequest3.GetRequestStream());
myWriter3.Write(postData1);
myWriter3.Close();
// Get the response.
HttpWebResponse myResponse3 = (HttpWebResponse)myRequest3.GetResponse();
// Open the stream using a StreamReader for easy access.
StreamReader myReader3 = new StreamReader(myResponse3.GetResponseStream());
// Read the content.
string output2 = myReader3.ReadToEnd();
// Clean up the streams and the response.
myReader3.Close();
myResponse3.Close();
All suggestions are welcome
posts os multipart/form-data type have a different structure because they are meant to transfer data and not just plain text.
Here's the format:
--[random number, a GUID is good here]
Content-Disposition: form-data; name="[name of variable]"
[actual value]
--[random number, a GUID is good here]--
Using HTTPWebRequest you can create a request that has that format. Here's a sample:
string boundary = Guid.NewGuid().ToString();
string header = string.Format("--{0}", boundary);
string footer = string.Format("--{0}--", boundary);
StringBuilder contents = new StringBuilder();
contents.AppendLine(header);
contents.AppendLine(header);
contents.AppendLine(String.Format("Content-Disposition: form-data; name=\"{0}\"", "username"));
contents.AppendLine();
contents.AppendLine("your_username");
contents.AppendLine(header);
contents.AppendLine(String.Format("Content-Disposition: form-data; name=\"{0}\"", "password"));
contents.AppendLine();
contents.AppendLine("your_password");
contents.AppendLine(footer);
The best way to send multipart form data in C# is shown in the snippet, here you see that adding different type of content is as easy as adding it to the wrapper multipart content type:
var documentContent = new MultipartFormDataContent();
documentContent.Add(new StringContent("AnalyticsPage.xlsx"), "title");
documentContent.Add(new ByteArrayContent(File.ReadAllBytes("C:\\Users\\awasthi\\Downloads\\AnalyticsPage.xlsx")), "file", "AnalyticsPage.xlsx");
Then just make an api call:
using (var client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true, CookieContainer = new CookieContainer() }))
{
response = client.PostAsync(documentAddApi, documentContent).Result;
var responseContent = response.Content.ReadAsStringAsync().Result;
}
Here the expectation is that the rest endpoint you are making a call to is accepting a 'title' field for the file and the byte array of the file named 'file'.
Here is an article on multipart form posts in C# with more detail. This code was eventually merged into RestSharp, which is an excellent library you could use to generate the request.
The format of multipart/form-data
requests is outlined here: http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2.
精彩评论