PHP can't get raw data sent as multipart/form-data - c#

This is client code (C#) :
string boundary = "--ABC";
try
{
WebRequest request = WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "multipart/form-data;boundary="+boundary;
using (var requestStream = request.GetRequestStream())
using (var writer = new StreamWriter(requestStream))
{
writer.WriteLine(boundary);
writer.WriteLine("Content-Disposition: form-data; name=\"data\"");
writer.WriteLine();
writer.WriteLine("abcdefg");
writer.WriteLine(boundary + "--");
writer.Flush();
}
string responseData = string.Empty;
using (var response = request.GetResponse())
using (var responseStream = response.GetResponseStream())
using (var reader = new StreamReader(responseStream))
{
responseData=reader.ReadToEnd();
}
and this is the server code (php):
print file_get_contents("php://input");
or:
print $_POST["data"];
or:
print $http_raw_post_data;
or:
$fp=fopen("php://output","rb");
$contents=fread($fp,5);
fclose($fp);
print $contents;
Non of these code working, all print empty.
Could any one help please?

The following example illustrates "multipart/form-data" encoding. Suppose we have the following form:
<FORM action="http://server.com/cgi/handle"
enctype="multipart/form-data"
method="post">
<P>
What is your name? <INPUT type="text" name="submit-name"><BR>
What files are you sending? <INPUT type="file" name="files"><BR>
<INPUT type="submit" value="Send"> <INPUT type="reset">
</FORM>
If the user enters "Larry" in the text input, and selects the text file "file1.txt", the user agent might send back the following data:
Content-Type: multipart/form-data; boundary=AaB03x
--AaB03x
Content-Disposition: form-data; name="submit-name"
Larry
--AaB03x
Content-Disposition: form-data; name="files"; filename="file1.txt"
Content-Type: text/plain
... contents of file1.txt ...
--AaB03x--
If the user selected a second (image) file "file2.gif", the user agent might construct the parts as follows:
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--
Multipart Form Post in C# Example

TRY THIS:
string boundary = "AaB03x";
try
{
WebRequest request = WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "multipart/form-data;boundary="+boundary;
using (var requestStream = request.GetRequestStream())
using (var writer = new StreamWriter(requestStream))
{
writer.WriteLine("--"+boundary);
writer.WriteLine( "Content-Disposition: form-data; name=\"files\"; filename=\"file1.txt\"");
writer.WriteLine("Content-Type: text/plain
");
writer.WriteLine("example");
writer.WriteLine("--"boundary + "--");
writer.Flush();
}
string responseData = string.Empty;
using (var response = request.GetResponse())
using (var responseStream = response.GetResponseStream())
using (var reader = new StreamReader(responseStream))
{
responseData=reader.ReadToEnd();
}

Related

convert curl command into c# code using httpclient

Command I need to convert :
curl.exe --digest -u login:pw -s -F "cert=#.\cert.pem" http://127.0.0.1/upload.htm
C# code I'm trying :
HttpClientHandler handler = new HttpClientHandler();
handler.Credentials = new NetworkCredential("login", "pw");
HttpClient client = new HttpClient(handler);
client.BaseAddress = new Uri("http://127.0.0.1");
...
var content = new StringContent(fileContents);
content.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "cert",
FileName = "cert.pem"
};
await client.PostAsync("/upload.htm", content);
Result :
<body><h1>HTTP/1.0 415 Unsupported Media Type</h1></body>
aldo tested the following c# code :
string executableLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
String path = Path.Combine(executableLocation, "cert.pem");
var fs = File.Open(path, FileMode.Open);
var multiPartContent = new MultipartFormDataContent();
var fc = new StreamContent(fs);
fc.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
multiPartContent.Add(fc, "certUsageUnspecified", "cert.pem");
var uploadCertificate = await client.PostAsync("/upload.htm", multiPartContent);
logger.Info(await uploadCertificate.Content.ReadAsStringAsync());
logger.Info("=== end upload certificate ===");
and result is the following :
<body><h1>HTTP/1.0 400 Bad Request</h1></body>
I don't know what I'm doing wrong there but I can't find the solution. It's working fine with the curl command.
curl -Fis for multipart -F, --form <name=content> Specify HTTP multipart POST data
Try the following:
var content = new MultipartFormDataContent();
var fs = File.Open(".\cert.pem", FileMode.Open);
var fc = new StreamContent(fs);
fc.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
content.Add(fc, "cert", "cert.pem");
For information only
curl headers received with a file cert.pem whose content is "cert".
POST
Partial body: --------------------------87b709a918c0166a
Content-Disposition: form-data; name="cert"; filename="cert.pem"
Content-Type: application/octet-stream
"cert"
--------------------------87b709a918c0166a--
Body: --------------------------87b709a918c0166a
Content-Disposition: form-data; name="cert"; filename="cert.pem"
Content-Type: application/octet-stream
"cert"
--------------------------87b709a918c0166a--
The equivalent received with proposed .NET code:
POST
Partial body: --7ee9988d-bfd9-46d6-b0c9-74af30d7a6a2
Content-Disposition: form-data; name=cert; filename=cert.pem; filename*=utf-8''cert.pem
Content-Type: application/octet-stream
"cert"
--7ee9988d-bfd9-46d6-b0c9-74af30d7a6a2--
Body: --7ee9988d-bfd9-46d6-b0c9-74af30d7a6a2
Content-Disposition: form-data; name=cert; filename=cert.pem; filename*=utf-8''cert.pem
Content-Type: application/octet-stream
"cert"
--7ee9988d-bfd9-46d6-b0c9-74af30d7a6a2--
This is not strictly the same for Content-Disposition: header value but its very close.

Unable to upload file using HTTP POST

I'm trying to upload a file using HTTP Post but somehow there is no file to be found when I process the request on the server side. I was able to create a similar request and successfully upload file using Chrome's Postman extension, but somehow can't do the same programmatically.
Client code:
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(fullUrl);
request.Method = "POST";
using (Stream requestStream = request.GetRequestStream())
{
string boundary = "----------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("--" + boundary + "\r\n");
byte[] trailer = System.Text.Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n");
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type:{2}\r\n\r\n";
string header = string.Format(headerTemplate, "Files", "myFile.xml", "text/xml");
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
requestStream.Write(boundarybytes, 0, boundarybytes.Length);
requestStream.Write(headerbytes, 0, headerbytes.Length);
requestStream.Write(uploadedFile, 0, uploadedFile.Length);
requestStream.Write(trailer, 0, trailer.Length);
}
The request looks like this (in Fiddler) :
POST https://host/myUrl
Content-Length: 1067
Expect: 100-continue
Connection: Keep-Alive
------------8d2942f79ab208e
Content-Disposition: form-data; name="Files"; filename="myFile.xml"
Content-Type:text/xml
<myFile>
Something
</myFile>
------------8d2942f79ab208e
Server side:
var httpRequest = HttpContext.Current.Request;
if (httpRequest.Files.Count != 1)
return BadRequest("Didn't get the file.");
But I always get httpRequest.Files.Count to be zero. Why?
The following request (created using Postman) gives me httpRequest.Files.Count to be one, as expected.
POST myUrl HTTP/1.1
Host: host
Cache-Control: no-cache
----WebKitFormBoundaryE19zNvXGzXaLvS5C
Content-Disposition: form-data; name="Files"; filename="myFile.xml"
Content-Type: text/xml
----WebKitFormBoundaryE19zNvXGzXaLvS5C
What am I doing wrong?
Figured it out. Thanks to this blog
Made two changes:
1) Added ContentType :
request.ContentType = "multipart/form-data; boundary=" + boundary;
2) Modified how the boundary ends
byte[] trailer = System.Text.Encoding.UTF8.GetBytes("\r\n--" + boundary + "--");
And it works now. Hope this helps someone.
Perhaps you need to set the request's content type to "multipart/form-data"
request.ContentType = "multipart/form-data";

using HttpWebRequest upload file (multipart/form-data)

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.

how to upload file via c# post request? ownCloud

i`m using ownCloud (open source cloud) and i have a form to upload files
the form sending the post request to upload.php file that handle the upload.
the request have a lot of fields and need to send all info and cookie.
i need to develop a c# code to upload files to the cloud.
the best way in my opinion is to make a request similar to the request that the form does.
what do you think? any suggestions?
p.s i read the following solutions but it is not working.
Sending Files using HTTP POST in c#
http://bytes.com/topic/c-sharp/answers/268661-how-upload-file-via-c-code
Upload files with HTTPWebrequest (multipart/form-data)
thanks
here is some of the code:
the form:
<form data-upload-id='1'
id="data-upload-form"
class="file_upload_form"
action="<?php print_unescaped(OCP\Util::linkTo('files', 'ajax/upload.php')); ?>"
method="post"
enctype="multipart/form-data"
target="file_upload_target_1">
<input type="hidden" name="MAX_FILE_SIZE" id="max_upload" value="<?php p($_['uploadMaxFilesize']) ?>">
<input type="hidden" name="requesttoken" value="<?php p($_['requesttoken']) ?>" id="requesttoken">
<input type="hidden" class="max_human_file_size" value="(max <?php p($_['uploadMaxHumanFilesize']); ?>)">
<input type="hidden" name="dir" value="<?php p($_['dir']) ?>" id="dir">
<input type="file" id="file_upload_start" name='files[]'/>
</form>
This the way the request seen to me:
enter code here
Request URL:http://my-url/owncloud/index.php/apps/files/ajax/upload.php
Request Method:POST
Status Code:200 OK
Request Headersview parsed
POST /owncloud/index.php/apps/files/ajax/upload.php HTTP/1.1
Host: my-url
Connection: keep-alive
Content-Length: 730
Accept: */*
requesttoken: 0bbcd458174e76e139ad
Origin: http://my-url
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryVhC3ZFEhWXiSUZYT
Referer: http://my-url/owncloud/index.php/apps/files
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Cookie: oc_username=tal; oc_token=f24c041e992624d10cabbaa16aa6aeea; oc_remember_login=1; __utma=220528984.2016256779.1375771228.1375771228.1375862096.2; __utmz=220528984.1375771228.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); olfsk=olfsk4827894743066281; hblid=QHgh67nWTyXfpzWe6B1Tj9Z3JM0QBCfA; 510e8a1de6274=eqavm1nikkon6ush7con3o6ar6
Request Payload
------WebKitFormBoundaryVhC3ZFEhWXiSUZYT
Content-Disposition: form-data; name="MAX_FILE_SIZE"
537919488
------WebKitFormBoundaryVhC3ZFEhWXiSUZYT
Content-Disposition: form-data; name="requesttoken"
0bbcd458174e76e139ad
------WebKitFormBoundaryVhC3ZFEhWXiSUZYT
Content-Disposition: form-data; name="dir"
/
------WebKitFormBoundaryVhC3ZFEhWXiSUZYT
Content-Disposition: form-data; name="files[]"; filename="bg.png"
Content-Type: image/png
------WebKitFormBoundaryVhC3ZFEhWXiSUZYT--
Response Headersview parsed
HTTP/1.1 200 OK
Date: Sun, 08 Sep 2013 07:21:02 GMT
Server: Apache/2.2.16 (Debian)
X-Powered-By: PHP/5.3.3-7+squeeze16
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
X-Content-Type-Options: nosniff
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 132
Keep-Alive: timeout=15, max=99
Connection: Keep-Alive
Content-Type: text/plain; charset=utf-8
i tried this code
public static void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc)
{
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);
//StreamReader reader3 = new StreamReader(rs);
rs.Close();
WebResponse wresp = null;
try
{
wresp = wr.GetResponse();
Stream stream2 = wresp.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
MessageBox.Show((string.Format("File uploaded, server response is: {0}", reader2.ReadToEnd())));
Debug.WriteLine(string.Format("File uploaded, server response is: {0}", reader2.ReadToEnd()));
}
catch(Exception ex)
{
Debug.WriteLine("Error uploading file", ex);
if(wresp != null)
{
wresp.Close();
wresp = null;
}
}
finally
{
wr = null;
}
}
the calling function:
NameValueCollection nvc = new NameValueCollection();
nvc.Add("id", "TTR");
nvc.Add("btn-submit-photo", "Upload");
FilesClass.HttpUploadFile("http://192.168.49.108/owncloud/index.php/apps/files/ajax/upload.php", #"C:\t.txt", "files[]", "text/plain", nvc);
the response from the server is {"data":{"message":"Authentication error"},"status":"error"}
that mean that i was rejected by upload.php
maybe i need to send the cookie?
Instead of trying to simulate a POST upload (which ownCloud makes fairly difficult due to security issues) you can use WebDAV to upload the file.
Simply send a PUT request to http://example.com/owncloud/remote.php/webdav/some/path

HTTP Post as IE6 using C#

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.

Categories

Resources