使用C#将HTTP发布为IE6
本文关键字:IE6 HTTP 使用 | 更新日期: 2023-09-27 18:19:35
我需要使用C#进行HTTPPOST。它需要以与IE6页面相同的方式进行回发。
从文档来看,回发应该看起来像
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--
我想我在边界字符方面有问题。我尝试在post数据中设置边界,fiddler显示了类似的内容,但我返回了一页,错误为"无效的过程调用或参数"。"内容"处置在正文而不是标头中,以将其保持在边界内。我不确定那是对的。我设定边界的方式正确吗有人能为如何使用C#进行IE6风格的HTTPPOST提供一些指导吗感谢
我的代码
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;
小提琴手输出(原始)
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--
我认为您有两个潜在的问题:
1) 您发送的URL对b_CustomerId参数的格式与IE6实现不同。如果您要定位的网站不期望HTML编码的值,那么这很容易成为错误消息的来源。
您的请求:
Upload.asp?b_customerId=%5BO/M1234%5D
IE6请求:
Upload.asp?b_customerId=[O/M1234]
为了解决此问题,您可以从Uri类构造函数的重载中创建一个新的Url,该类构造函数已标记为过时,但仍然可以正常工作。此重载允许您指定字符串已在第二个参数中转义。
为了使用此构造函数,请更改此行:
request = (HttpWebRequest)WebRequest.Create(url);
到此:
request = (HttpWebRequest)WebRequest.Create(new Uri(url, true));
2) Content disposition标记在您的请求中的格式与IE6请求中的不同。
您的请求:
Content-disposition: form-data; name="File1";
filename="provideTest.xml"
IE6请求:
Content-disposition: form-data; name=”File1”; filename=”noColonsSpacesOrAmpersandsInHere”
这可以通过更改以下两条线来解决:
"Content-disposition: form-data; name='"File1'";" + Environment.NewLine +
"filename='"provideTest.xml'"" + Environment.NewLine +
至:
"Content-disposition: form-data; name='"File1'"; " +
"filename='"provideTest.xml'"" + Environment.NewLine +
我在博客中介绍了一种使用WebClient上传多个文件的方法,以及发送参数的可能性。这是相关代码:
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; }
}
然后是一种执行上传的方法:
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();
}
}
可以这样使用:
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);
}
这不是一个完整的答案,但您可以考虑使用套接字而不是WebRequest,并自己执行HTTP请求。服务器上的多部分处理程序似乎不符合规则,并且希望请求与IE6的请求相同,因此模拟自己将是最好的方法。