C#模拟提交表单 post-带附件的表单
普通的模拟提交表单的操作只要构建html协议中的数据就行,但是表单中如果含有file的话, 也就是说含有附件上传的内容的话怎样提交呢?
使用multipart/form-data发送文件
如果要在客户端向服务器上传文件,我们就必须模拟一个POST multipart/form-data类型的请求,Content-Type必须是multipart/form-data。
以multipart/form-data编码的POST请求格式与application/x-www-form-urlencoded完全不同,multipart/form-data需要首先在HTTP请求头设置一个分隔符,例如ABCD:
我们模拟的提交要设定 content-type不同于非含附件的post时候的content-type,这里需要: (“Content-Type”, “multipart/form-data; boundary=ABCD”);
然后,将每个字段用“–分隔符”分隔,最后一个“–分隔符–”表示结束。例如,要上传一个title字段”Today”和一个文件C:\1.txt,HTTP正文如下:
–ABCD
Content-Disposition: form-data; name=”title”
\r\n
Today
–ABCD
Content-Disposition: form-data; name=”1.txt”; filename=”C:\1.txt”
Content-Type: text/plain
\r\n
<这里是1.txt文件的内容>
–ABCD–
\r\n
请注意,每一行都必须以\r\n结束,包括最后一行。
如果用Sniffer程序检测IE发送的POST请求,可以发现IE的分隔符类似于——7d4a6d158c9,这是IE产生的一个随机数,目的是防止上传文件中出现分隔符导致服务器无法正确识别文件起始位置。我们可以写一个固定的分隔符,只要足够复杂即可。
下面是一段java的post 带附件的模拟发送程序段:
发送文件的POST代码如下:
String[] props = … // 字段名
String[] values = … // 字段值
byte[] file = … // 文件内容
String BOUNDARY = “—————————7d4a6d158c9”; // 分隔符
StringBuffer sb = new StringBuffer();// 发送每个字段
:for(int i=0; i sb = sb.append(“–“);
sb = sb.append(BOUNDARY);
sb = sb.append(“\r\n”);
sb = sb.append(“Content-Disposition: form-data; name=\””+ props[i] + “\”\r\n\r\n”);
sb = sb.append(URLEncoder.encode(values[i]));
sb = sb.append(“\r\n”);
}// 发送文件:sb = sb.append(“–“);
sb = sb.append(BOUNDARY);
sb = sb.append(“\r\n”);
sb = sb.append(“Content-Disposition: form-data; name=\”1\”; filename=\”1.txt\”\r\n”);
sb = sb.append(“Content-Type: application/octet-stream\r\n\r\n”);
byte[] data = sb.toString().getBytes();
byte[] end_data = (“\r\n–” + BOUNDARY + “–\r\n”).getBytes();// 设置HTTP头:
hc.setRequestProperty(“Content-Type”, MULTIPART_FORM_DATA + “;
boundary=” + BOUNDARY);
hc.setRequestProperty(“Content-Length”, String.valueOf(data.length + file.length + end_data.length));
// 输出:output = hc.openOutputStream();output.write(data);output.write(file);output.write(end_data);
// 读取服务器响应:
// TODO…