使用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--

使用C#将HTTP发布为IE6

我认为您有两个潜在的问题:

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的请求相同,因此模拟自己将是最好的方法。