How to simulate browser file upload with HttpWebRequest
guys, first of all thanks for your contributions, I've found great responses here. Yet I've ran into a problem I can't figure out and if someone could provide any help, it would be greatly appreciated.
I'm developing this application in C# that could upload an image from computer to user photoblog. For this I'm usig pixelpost platform for photoblogs that is written mainly in PHP.
I've searched here and on other web pages, but the exmples provided there didn't work for me. Here is what I used in my example: (Upload files with HTTPWebrequest (multipart/form-data)) and (http://bytes.com/topic/c-sharp/answers/268661-how开发者_如何学C-upload-file-via-c-code) Once it is ready I will make it available for free on the internet and maybe also create a windows mobile version of it, since I'm a fan of pixelpost.
here is the code I've used:
string formUrl = "http://localhost/pixelpost/admin/index.php?x=login";
string formParams = string.Format("user={0}&password={1}", "user-String", "password-String");
string cookieHeader;
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(formUrl);
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
req.AllowAutoRedirect = false;
byte[] bytes = Encoding.ASCII.GetBytes(formParams);
req.ContentLength = bytes.Length;
using (Stream os = req.GetRequestStream())
{
os.Write(bytes, 0, bytes.Length);
}
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
cookieHeader = resp.Headers["Set-Cookie"];
string pageSource;
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
pageSource = sr.ReadToEnd();
Console.WriteLine();
}
string getUrl = "http://localhost/pixelpost/admin/index.php";
HttpWebRequest getRequest = (HttpWebRequest)HttpWebRequest.Create(getUrl);
getRequest.Headers.Add("Cookie", cookieHeader);
HttpWebResponse getResponse = (HttpWebResponse)getRequest.GetResponse();
using (StreamReader sr = new StreamReader(getResponse.GetResponseStream()))
{
pageSource = sr.ReadToEnd();
}
// end first part: login to admin panel
long length = 0;
string boundary = "----------------------------" +
DateTime.Now.Ticks.ToString("x");
HttpWebRequest httpWebRequest2 = (HttpWebRequest)WebRequest.Create("http://localhost/pixelpost/admin/index.php?x=save");
httpWebRequest2.ContentType = "multipart/form-data; boundary=" + boundary;
httpWebRequest2.Method = "POST";
httpWebRequest2.AllowAutoRedirect = false;
httpWebRequest2.KeepAlive = false;
httpWebRequest2.Credentials = System.Net.CredentialCache.DefaultCredentials;
httpWebRequest2.Headers.Add("Cookie", cookieHeader);
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}";
string formitem = string.Format(formdataTemplate, "headline", "image-name");
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
memStream.Write(formitembytes, 0, formitembytes.Length);
memStream.Write(boundarybytes, 0, boundarybytes.Length);
string headerTemplate = "\r\nContent-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n";
string header = string.Format(headerTemplate, "userfile", "path-to-the-local-file");
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
memStream.Write(headerbytes, 0, headerbytes.Length);
FileStream fileStream = new FileStream("path-to-the-local-file", FileMode.Open, FileAccess.Read);
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.Length);
fileStream.Close();
httpWebRequest2.ContentLength = memStream.Length;
Stream requestStream = httpWebRequest2.GetRequestStream();
memStream.Position = 0;
byte[] tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer, 0, tempBuffer.Length);
memStream.Close();
requestStream.Write(tempBuffer, 0, tempBuffer.Length);
requestStream.Close();
WebResponse webResponse2 = httpWebRequest2.GetResponse();
Stream stream2 = webResponse2.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
Console.WriteLine(reader2.ReadToEnd());
webResponse2.Close();
httpWebRequest2 = null;
webResponse2 = null;
and also here is the PHP: (http://dl.dropbox.com/u/3149888/index.php) and (http://dl.dropbox.com/u/3149888/new_image.php)
the mandatory fields are headline and userfile so I can't figure out where the mistake is, as the format sent in right. I'm guessing there is something wrong with the octet-stream sent to the form. Maybe it's a stupid mistake I wasn't able to trace, in any case, if you could help me that would mean a lot.
thanks,
So Martin helped me out here and I was able to make the important changes to the code above in order for it to work properly. The Content-Type had to be changed to image/jpeg. Also I used C# Image type to send image stream.
Also pay attention to the Stream format, as it does not have to contain extra spaces or new lines.
here is the changed part:
string formUrl = "http://localhost/pixelpost/admin/index.php?x=login";
string formParams = string.Format("user={0}&password={1}", "username", "password");
string cookieHeader;
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(formUrl);
req.ContentType = "application/x-www-form-urlencoded";
req.Method = "POST";
req.AllowAutoRedirect = false;
byte[] bytes = Encoding.ASCII.GetBytes(formParams);
req.ContentLength = bytes.Length;
using (Stream os = req.GetRequestStream())
{
os.Write(bytes, 0, bytes.Length);
}
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
cookieHeader = resp.Headers["Set-Cookie"];
string pageSource;
using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
{
pageSource = sr.ReadToEnd();
}
string getUrl = "http://localhost/pixelpost/admin/index.php";
HttpWebRequest getRequest = (HttpWebRequest)HttpWebRequest.Create(getUrl);
getRequest.Headers.Add("Cookie", cookieHeader);
HttpWebResponse getResponse = (HttpWebResponse)getRequest.GetResponse();
using (StreamReader sr = new StreamReader(getResponse.GetResponseStream()))
{
pageSource = sr.ReadToEnd();
}
long length = 0;
string boundary = "----------------------------" +
DateTime.Now.Ticks.ToString("x");
HttpWebRequest httpWebRequest2 = (HttpWebRequest)WebRequest.Create("http://localhost/pixelpost/admin/index.php?x=save");
httpWebRequest2.ContentType = "multipart/form-data; boundary=" + boundary;
httpWebRequest2.Method = "POST";
httpWebRequest2.AllowAutoRedirect = false;
httpWebRequest2.KeepAlive = false;
httpWebRequest2.Credentials = System.Net.CredentialCache.DefaultCredentials;
httpWebRequest2.Headers.Add("Cookie", cookieHeader);
Stream memStream = new System.IO.MemoryStream();
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary);
string headerTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: image/jpeg\r\n\r\n";
string header = string.Format(headerTemplate, "userfile", "Sunset.jpg");
byte[] headerbytes = System.Text.Encoding.ASCII.GetBytes(header);
memStream.Write(headerbytes, 0, headerbytes.Length);
Image img = null;
img = Image.FromFile("C:/Documents and Settings/Dorin Cucicov/My Documents/My Pictures/Sunset.jpg", true);
img.Save(memStream, System.Drawing.Imaging.ImageFormat.Jpeg);
memStream.Write(boundarybytes, 0, boundarybytes.Length);
string formdataTemplate = "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";
string formitem = string.Format(formdataTemplate, "headline", "Sunset");
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
memStream.Write(formitembytes, 0, formitembytes.Length);
memStream.Write(boundarybytes, 0, boundarybytes.Length);
httpWebRequest2.ContentLength = memStream.Length;
Stream requestStream = httpWebRequest2.GetRequestStream();
memStream.Position = 0;
byte[] tempBuffer = new byte[memStream.Length];
memStream.Read(tempBuffer, 0, tempBuffer.Length);
memStream.Close();
requestStream.Write(tempBuffer, 0, tempBuffer.Length);
requestStream.Close();
WebResponse webResponse2 = httpWebRequest2.GetResponse();
Stream stream2 = webResponse2.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
Console.WriteLine(reader2.ReadToEnd());
webResponse2.Close();
httpWebRequest2 = null;
webResponse2 = null;
Thank you all again for answering or just reading.
精彩评论