I'm developing an Android application and sending a multipart-form-data HTTP POST to my IIS server. I need to see the raw HTTP message that my server is receiving. For this, in visual studio 2013 I put an interrupt just after this line
public String Report([Bind(Include = "lasfotos,comentario,asunto")] HttpPostedFileBase lasfotos, string comentario, string asunto)
In local variables i can see a lot of information inside this>base>request about the http message like path, content lenght, etc but i can't find where the raw HTTP is.
edit: Why do i think that see the raw http is a solution? because i can easily find my problem here i think. But i will show you my base problem:
I have this function in java that send's the data to the server. i can see my variable values (in the server) of "comentario" and "asunto" but "lasfotos" = null
public static String Postear(ArrayList<File> files, String asunto, String detalle)
{
String respuesta;
try
{
String boundary = "qu1ckr3port_myb0undy";
String filesboundary = "boundy_4_files";
URL url = new URL("http://192.168.10.100/QuickReport/Uploads/Report");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
outputStream.writeBytes("--"+boundary+"\r\n" +
"Content-Disposition: form-data; name=\"lasfotos\"\r\n" +
"Content-Type: multipart/mixed; boundary="+filesboundary+"\r\n\r\n");
for (byte i = 0; i < files.size(); i++)
{
outputStream.writeBytes("--"+filesboundary+"\r\n" +
"Content-Disposition: file; filename=\"" + files.get(i).getName() + "\"\r\n" +
"Content-Type: image/jpeg\r\n\r\n");
FileInputStream fileInputStream = new FileInputStream(files.get(i));
int bytesAvailable = fileInputStream.available();
int bufferSize = Math.min(bytesAvailable, 1024 * 1024);
byte[] buffer = new byte[bufferSize];
int bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0)
{
outputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, 1024 * 1024);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
fileInputStream.close();
outputStream.writeBytes("\r\n");
}
outputStream.writeBytes("--"+filesboundary+"--\r\n" +
"--"+boundary+"\r\n" +
"Content-Disposition: form-data; name=\"comentario\"\r\n\r\n" +
detalle + "\r\n" +
"--"+boundary+"\r\n");
outputStream.writeBytes("\r\n" +
"--"+boundary+"\r\n" +
"Content-Disposition: form-data; name=\"asunto\"\r\n\r\n" +
asunto + "\r\n" +
"--"+boundary+"--\r\n");
respuesta = "";
String linea;
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
while ((linea = reader.readLine()) != null) respuesta += linea;
reader.close();
outputStream.flush();
outputStream.close();
} catch (Exception e)
{
respuesta = "error";
e.printStackTrace();
}
return respuesta;
}
the problem was bad documentation i think. i followed the format documented in this page http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2
Content-Type: multipart/form-data; boundary=AaB03x
--AaB03x
Content-Disposition: form-data; name="submit-name"
Larry
--AaB03x
Content-Disposition: form-data; name="files"
Content-Type: multipart/mixed; boundary=BbC04y
--BbC04y
Content-Disposition: file; filename="file1.txt"
Content-Type: text/plain
... contents of file1.txt ...
--BbC04y
Content-Disposition: file; filename="file2.gif"
Content-Type: image/gif
Content-Transfer-Encoding: binary
...contents of file2.gif...
--BbC04y--
--AaB03x--
and that was the problem. i just changed my code and now is working perfectly. here is my new code:
public static String Postear(ArrayList<File> files, String asunto, String detalle)
{
String respuesta;
try
{
String boundary = "qu1ckr3port_myb0undy";
URL url = new URL("http://192.168.10.100/QuickReport/Uploads/Report");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
for (byte i = 0; i < files.size(); i++)
{
outputStream.writeBytes("--"+boundary+"\r\n" +
"Content-Disposition: form-data; name=\"lasfotos\" filename=\"" + files.get(i).getName() + "\"\r\n" +
"Content-Type: image/jpeg\r\n\r\n");
FileInputStream fileInputStream = new FileInputStream(files.get(i));
int bytesAvailable = fileInputStream.available();
int bufferSize = Math.min(bytesAvailable, 1024 * 1024);
byte[] buffer = new byte[bufferSize];
int bytesRead = fileInputStream.read(buffer, 0, bufferSize);
while (bytesRead > 0)
{
outputStream.write(buffer, 0, bufferSize);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, 1024 * 1024);
bytesRead = fileInputStream.read(buffer, 0, bufferSize);
}
fileInputStream.close();
outputStream.writeBytes("\r\n");
}
outputStream.writeBytes("--"+boundary+"\r\n" +
"Content-Disposition: form-data; name=\"comentario\"\r\n\r\n" +
detalle + "\r\n");
outputStream.writeBytes("\r\n" +
"--"+boundary+"\r\n" +
"Content-Disposition: form-data; name=\"asunto\"\r\n\r\n" +
asunto + "\r\n" +
"--"+boundary+"--\r\n");
respuesta = "";
String linea;
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
while ((linea = reader.readLine()) != null) respuesta += linea;
reader.close();
outputStream.flush();
outputStream.close();
} catch (Exception e)
{
respuesta = "error";
e.printStackTrace();
}
return respuesta;
}
hope this be usefull for someone...
Related
I'm making a Windows Application that need to make a HTTP post to my Server. In my .NET MVC application i use this code:
Html.BeginForm("Index","UploadData",
FormMethod.Post,
new { enctype = "multipart/form-data", #class = "contact-form", id = "frmUploadData" })
My question is how do i post a File from my computer to the server from a windows forms application?
I have tried to use, this method, but i am not sure how to call it correctly:
public static void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc)
{
Console.WriteLine(string.Format("Uploading {0} to {1}", file, url));
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
wr.ContentType = "multipart/form-data; boundary=" + boundary;
wr.Method = "POST";
wr.KeepAlive = true;
wr.Credentials = System.Net.CredentialCache.DefaultCredentials;
Stream rs = wr.GetRequestStream();
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
foreach (string key in nvc.Keys)
{
rs.Write(boundarybytes, 0, boundarybytes.Length);
string formitem = string.Format(formdataTemplate, key, nvc[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
rs.Write(formitembytes, 0, formitembytes.Length);
}
rs.Write(boundarybytes, 0, boundarybytes.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
string header = string.Format(headerTemplate, paramName, file, contentType);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);
FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
rs.Write(buffer, 0, bytesRead);
}
fileStream.Close();
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
rs.Write(trailer, 0, trailer.Length);
rs.Close();
WebResponse wresp = null;
try
{
wresp = wr.GetResponse();
Stream stream2 = wresp.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
Console.WriteLine(string.Format("File uploaded, server response is: {0}", reader2.ReadToEnd()));
}
catch (Exception ex)
{
Console.WriteLine("Error uploading file", ex);
if (wresp != null)
{
wresp.Close();
wresp = null;
}
}
finally
{
wr = null;
}
}
Not sure if i am calling it correctly, i get a 404 error when i try to call this method:
public static void OnChanged(object sender, FileSystemEventArgs e)
{
NameValueCollection nvc = new NameValueCollection();
nvc.Add("id", "frmUploadData");
HttpUploadFile("http://classicraider.com/UploadData",
#e.FullPath, "file", "lua", nvc);
Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
}
I was trying to upload file to web server through API but i got error
"The remote server returned an error: (403) Forbidden." I also try upload file via postman and it was successful.Below my code uploading file and postman preview.
public static void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc)
{
MessageBox.Show(string.Format("Uploading {0} to {1}", file, url));
var boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
var boundarybytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
var wr = (HttpWebRequest)WebRequest.Create(url);
wr.ContentType = "multipart/form-data; boundary=" + boundary;
wr.Method = "POST";
wr.KeepAlive = true;
wr.Credentials = CredentialCache.DefaultCredentials;
var rs = wr.GetRequestStream();
const string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
foreach (string key in nvc.Keys)
{
rs.Write(boundarybytes, 0, boundarybytes.Length);
var formitem = string.Format(formdataTemplate, key, nvc[key]);
byte[] formitembytes = Encoding.UTF8.GetBytes(formitem);
rs.Write(formitembytes, 0, formitembytes.Length);
}
rs.Write(boundarybytes, 0, boundarybytes.Length);
const string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
var header = string.Format(headerTemplate, paramName, file, contentType);
var headerbytes = Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);
var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
var buffer = new byte[4096];
var bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
rs.Write(buffer, 0, bytesRead);
}
fileStream.Close();
var trailer = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
rs.Write(trailer, 0, trailer.Length);
rs.Close();
WebResponse wresp = null;
try
{
wresp = wr.GetResponse();
var stream2 = wresp.GetResponseStream();
var reader2 = new StreamReader(stream2);
MessageBox.Show(string.Format("Response is: {0}", reader2.ReadToEnd()));
}
catch (Exception ex)
{
MessageBox.Show("Error uploading file" + ex);
if (wresp != null)
{
wresp.Close();
wresp = null;
}
}
finally
{
wr = null;
}
}
this is postman preview
POST / HTTP/1.1
Host: buckname.s3.amazonaws.com
Cache-Control: no-cache
----WebKitFormBoundaryE19zNvXGzXaLvS5C
Content-Disposition: form-data; name="key"
2014/6b9830b098c9871c6356a5e55af91bfd/${filename}
----WebKitFormBoundaryE19zNvXGzXaLvS5C
Content-Disposition: form-data; name="AWSAccessKeyId"
AKIAJNXK6LUBUSZBXJIQ
----WebKitFormBoundaryE19zNvXGzXaLvS5C
Content-Disposition: form-data; name="acl"
public-read
----WebKitFormBoundaryE19zNvXGzXaLvS5C
Content-Disposition: form-data; name="policy"
eyJleHBpcmF0aW9uIjoiMjAxNC0wOC0yMlQxMDo1MTow
----WebKitFormBoundaryE19zNvXGzXaLvS5C
Content-Disposition: form-data; name="signature"
ezYsOF/P6bGcOqQdyJeE7iApu2A=
----WebKitFormBoundaryE19zNvXGzXaLvS5C
Content-Disposition: form-data; name="success_action_status"
201
----WebKitFormBoundaryE19zNvXGzXaLvS5C
Content-Disposition: form-data; name="secure"
true
----WebKitFormBoundaryE19zNvXGzXaLvS5C
Content-Disposition: form-data; name="x-amz-storage-class"
REDUCED_REDUNDANCY
----WebKitFormBoundaryE19zNvXGzXaLvS5C
Content-Disposition: form-data; name="file"; filename="exp.png"
Content-Type: image/png
----WebKitFormBoundaryE19zNvXGzXaLvS5C
Content-Disposition: form-data; name="Content-Type"
image/jpeg
----WebKitFormBoundaryE19zNvXGzXaLvS5C
edit (code sending)
var nvc = new NameValueCollection
{
{"AWSAccessKeyId", fields.AWSAccessKeyId},
{"Content-Type", "image/jpeg"},
{"acl", fields.acl},
{"key", fields.key},
{"policy", fields.policy},
{"secure", secure.ToString()},
{"signature", signature},
{"success_action_status", fields.success_action_status},
{"x-amz-storage-class", "REDUCED_REDUNDANCY"}
};
HttpUploadHelper.HttpUploadFile(responsFieldsDeSerial.url.ToString(),#"C:\1.png", "file", "image/jpeg",nvc);
thank you!
My error was
<?xml version="1.0" encoding="UTF-8"?> <Error><Code>AccessDenied</Code><Message>Invalid according to Policy: Policy Condition failed: ["eq", "$Secure", "true"]</Message>
Problem was value of field (in my case : secure) case senstive i tried to post True but it must be true.
I want to keep it as simple as possible -
-We switched from an Godaddy windows hosting to Godaddy linux hosting
-After switching i get internal server error 500 when iam using POST from an c#
program(compact framework) with the content type - multipartformdata,
However i can still use a normal html form that sits on the server to post with no issues.
-Everything worked absolutly fine before the switch! I can still do GET requests,
and even normal(Not multipart/form-data) POST request from my C# app .
Headers and content from the request / response using the code below :
Request headers -
POST /users/test.php HTTP/1.1
Content-Type: multipart/form-data; boundary=----------------------------8d0cb969d25c418
Host: mydomain(i censor)
Content-Length: 403
Expect: 100-continue
Connection: Keep-Alive
Request content -
------------------------------8d0cb969d25c418
Content-Disposition: form-data; name="title";
test
------------------------------8d0cb969d25c418
Content-Disposition: form-data; name="pwd";
testpwd
------------------------------8d0cb969d25c418
Content-Disposition: form-data; name="file"; filename=test.txt
Content-Type: text/html
testfile
------------------------------8d0cb969d25c418
Response headers -
HTTP/1.1 500 Internal Server Error
Date: Fri, 20 Dec 2013 10:32:01 GMT
Server: Apache mod_fcgid/2.3.10-dev
Content-Length: 662
Keep-Alive: timeout=5
Connection: Keep-Alive
Content-Type: text/html; charset=iso-8859-1
This is my C# Code(Note - I must use compact framework only) :
openFileDialog1.ShowDialog();
NameValueCollection formsdata = new NameValueCollection();
formsdata.Add("title", textBox3.Text);
formsdata.Add("pwd", textBox4.Text);
string[] names = new string[1] { openFileDialog1.FileName };
UploadFilesToRemoteUrl("http://mydomain/users/writefile.php", names, "notused", formsdata, openFileDialog1.SafeFileName);
and for the method UploadFilesToRemoteUrl -
public static void UploadFilesToRemoteUrl(string url, string[] files, string
logpath, NameValueCollection nvc, string filename)
{
long length = 0;
string boundary = "----------------------------" +
DateTime.Now.Ticks.ToString("x");
HttpWebRequest httpWebRequest2 = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest2.ContentType = "multipart/form-data; boundary=" +
boundary;
httpWebRequest2.Method = "POST";
httpWebRequest2.KeepAlive = true;
httpWebRequest2.Credentials =
System.Net.CredentialCache.DefaultCredentials;
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.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=" + filename + "\r\n Content-Type: text/html\r\n\r\n";
for (int i = 0; i < files.Length; i++)
{
//string header = string.Format(headerTemplate, "file" + i, files[i]);
string header = string.Format(headerTemplate, "file", files[i]);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
memStream.Write(headerbytes, 0, headerbytes.Length);
FileStream fileStream = new FileStream(files[i], 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);
MessageBox.Show(reader2.ReadToEnd());
webResponse2.Close();
httpWebRequest2 = null;
webResponse2 = null;
}
Any help is really highly appreciated!
I cannot seem to get this code to work with Streamsends API. I have been all over the internet and have found very little info pertaining to what I am trying to do. I am trying to upload a file to their server. Can anyone look at this and maybe help me out here?
I keep getting a 500 error from Streamsends servers which they say is within the Streamsend application itself. What is funny is if I take the line near the bottom that is commented out
(//request.ContentType = "multipart/form-data";)
and uncomment it I get a 422 error which is saying invalid data. It seems like there is something wrong with the boundary.
I am fairly new to C# and this is the first time I have worked with Streamsends API so any help would be greatly appreciated.
m_Method = "POST"
m_Action = "uploads"
private string StreamSendResponse(string Path, string FileName)
{
string sReturn = String.Empty;
string sLocation = String.Empty;
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = Encoding.ASCII.GetBytes(Environment.NewLine + "--" + boundary + Environment.NewLine);
Uri addy = new Uri(m_URI + m_Action);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(addy);
request.ContentType = "multipart/form-data; boundary=" + boundary;
request.Method = m_Method;
request.KeepAlive = true;
request.Headers.Add("Authorization", "Basic " + Merv.base64Encode(m_ID + ":" + m_Key));
Stream rs = request.GetRequestStream();
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n{1}";
NameValueCollection nvc = new NameValueCollection();
foreach (string key in nvc.Keys)
{
rs.Write(boundarybytes, 0, boundarybytes.Length);
string formitem = string.Format(formdataTemplate, key, nvc[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
rs.Write(formitembytes, 0, formitembytes.Length);
}
rs.Write(boundarybytes, 0, boundarybytes.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n Content-Type: application/octet-stream\r\n";
string header = string.Format(headerTemplate, "data", FileName);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);
FileStream fileStream = new FileStream(Path + FileName, FileMode.Open, FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
rs.Write(buffer, 0, bytesRead);
}
fileStream.Close();
byte[] trailer = System.Text.Encoding.ASCII.GetBytes(Environment.NewLine + "--" + boundary + "--" + Environment.NewLine);
rs.Write(trailer, 0, trailer.Length);
rs.Close();
request.Accept = "application/xml";
//request.ContentType = "multipart/form-data";
try
{
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader srResponse = new StreamReader(response.GetResponseStream());
sLocation = response.Headers["Location"];
sReturn = srResponse.ReadToEnd().Trim();
}
catch (WebException exc)
{
StreamReader srResponse = new StreamReader(response.GetResponseStream());
sReturn = srResponse.ReadToEnd().Trim();
sLocation = exc.Message;
}
if (sReturn == String.Empty)
{
sReturn = sLocation;
}
return sReturn;
}
I need to do a HTTP POST using C#. It needs to do a postback the same way as an IE6 page.
From the documentation the postback should look like
POST /.../Upload.asp?b_customerId=[O/M1234] HTTP/1.1
Content-length: 12345
Content-type: multipart/form-data; boundary=vxvxv
Host: www.foo.com
--vxvxv
Content-disposition: form-data; name=”File1”; filename=”noColonsSpacesOrAmpersandsInHere”
Content-type: text/xml
<?xml version=”1.0” encoding=”UTF-8”?>
...
<bat:Batch ...
.......
</bat:Batch>
--vxvxv--
I think im having trouble with the boundary characters. I tried setting the boundary in the post data and fiddler shows something similar but I get a page back with the error "Invalid procedure call or argument". the Content-disposition is in the body rather than the header to keep it within the boundaries. Im not sure that is right. Am I setting the boundary the correct way? Can anyone give some guidance on how to do an IE6 style HTTP POST using C# ? Thanks
My Code
data = "--vxvxv" + Environment.NewLine +
"Content-disposition: form-data; name=\"File1\";" + Environment.NewLine +
"filename=\"provideTest.xml\"" + Environment.NewLine +
"Content-type: text/xml" + Environment.NewLine +
#"<?xml version=""1.0"" encoding=""UTF-8""?>" + Environment.NewLine +
data + Environment.NewLine +
"--vxvxv--";
var encoding = ASCIIEncoding.UTF8;
HttpWebRequest request;
var postData = encoding.GetBytes(data);
request = (HttpWebRequest)WebRequest.Create(url);
request.ContentLength = postData.Length;
request.Method = "POST";
request.ContentType = "multipart/form-data; boundary=vxvxv";
request.Host = "www.foo.com";
request.ContentLength = postData.Length;
X509Certificate2Collection certCollect = new X509Certificate2Collection();
X509Certificate2 cert = new X509Certificate2(#"C:\a\cert.pfx", "password");
certCollect.Add(cert);
request.ClientCertificates = certCollect;
using (Stream writeStream = request.GetRequestStream()) {
writeStream.Write(postData, 0, postData.Length); }
WebResponse webResponse = request.GetResponse();
string output = new StreamReader(webResponse.GetResponseStream()).ReadToEnd();
LogEntry.Write("Recieved : " + output);
return output;
Fiddler Output (raw)
POST https://../Upload.asp?b_customerId=%5BO/M1234%5D HTTP/1.1
Content-Type: multipart/form-data; boundary=vxvxv
Host: www.foo.com
Content-Length: 5500
Expect: 100-continue
Connection: Keep-Alive
--vxvxv
Content-disposition: form-data; name="File1";
filename="provideTest.xml"
Content-type: text/xml
<?xml version="1.0" encoding="UTF-8"?>
...SNIP...
</bat:Batch>
--vxvxv--
I think that you have two potential problems:
1) The URL that you are sending formats the b_CustomerId parameter differently than the IE6 implementation. If the site you are targeting does not expect an HTML-encoded value, this could very easily be the source of the error message.
Your request:
Upload.asp?b_customerId=%5BO/M1234%5D
The IE6 request:
Upload.asp?b_customerId=[O/M1234]
In order to fix this issue, you can create a new Url from an overload of the Uri class constructor that has been marked as obsolete, but still works correctly. This overload allows you to specify that the string has already been escaped in the second parameter.
In order to use this constructor, change this line:
request = (HttpWebRequest)WebRequest.Create(url);
to this:
request = (HttpWebRequest)WebRequest.Create(new Uri(url, true));
2) The Content-disposition tag is not formatted the same way in your request as it is in the IE6 request.
Your request:
Content-disposition: form-data; name="File1";
filename="provideTest.xml"
IE6 request:
Content-disposition: form-data; name=”File1”; filename=”noColonsSpacesOrAmpersandsInHere”
This can be resolved by changing these two lines:
"Content-disposition: form-data; name=\"File1\";" + Environment.NewLine +
"filename=\"provideTest.xml\"" + Environment.NewLine +
to:
"Content-disposition: form-data; name=\"File1\"; " +
"filename=\"provideTest.xml\"" + Environment.NewLine +
I have blogged about a way of uploading multiple files using a WebClient and the possibility to send parameters as well. Here's the relevant code:
public class UploadFile
{
public UploadFile()
{
ContentType = "application/octet-stream";
}
public string Name { get; set; }
public string Filename { get; set; }
public string ContentType { get; set; }
public Stream Stream { get; set; }
}
and then a method to perform the upload:
public byte[] UploadFiles(string address, IEnumerable<UploadFile> files, NameValueCollection values)
{
var request = WebRequest.Create(address);
request.Method = "POST";
var boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x", NumberFormatInfo.InvariantInfo);
request.ContentType = "multipart/form-data; boundary=" + boundary;
boundary = "--" + boundary;
using (var requestStream = request.GetRequestStream())
{
// Write the values
foreach (string name in values.Keys)
{
var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"{1}{1}", name, Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.UTF8.GetBytes(values[name] + Environment.NewLine);
requestStream.Write(buffer, 0, buffer.Length);
}
// Write the files
foreach (var file in files)
{
var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.UTF8.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"{2}", file.Name, file.Filename, Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.ASCII.GetBytes(string.Format("Content-Type: {0}{1}{1}", file.ContentType, Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
file.Stream.CopyTo(requestStream);
buffer = Encoding.ASCII.GetBytes(Environment.NewLine);
requestStream.Write(buffer, 0, buffer.Length);
}
var boundaryBuffer = Encoding.ASCII.GetBytes(boundary + "--");
requestStream.Write(boundaryBuffer, 0, boundaryBuffer.Length);
}
using (var response = request.GetResponse())
using (var responseStream = response.GetResponseStream())
using (var stream = new MemoryStream())
{
responseStream.CopyTo(stream);
return stream.ToArray();
}
}
which could be used like so:
using (var stream1 = File.Open("test.txt", FileMode.Open))
using (var stream2 = File.Open("test.xml", FileMode.Open))
using (var stream3 = File.Open("test.pdf", FileMode.Open))
{
var files = new[]
{
new UploadFile
{
Name = "file",
Filename = "test.txt",
ContentType = "text/plain",
Stream = stream1
},
new UploadFile
{
Name = "file",
Filename = "test.xml",
ContentType = "text/xml",
Stream = stream2
},
new UploadFile
{
Name = "file",
Filename = "test.pdf",
ContentType = "application/pdf",
Stream = stream3
}
};
var values = new NameValueCollection
{
{ "key1", "value1" },
{ "key2", "value2" },
{ "key3", "value3" },
};
byte[] result = UploadFiles("http://localhost:1234/upload", files, values);
}
This won't be a complete answer, but you could look at using a socket instead of WebRequest and performing the HTTP request yourself. It seems that the multipart handler on your server is non-conformi g and expects the request to be the same as IE6 would make, so emulating that yourself would be the best approach.