问题的起因是现在做的一个WEB API项目中需要以formdata的方式向后台提交数据(包括一个JSON和一张图片)。
之前一直是用以下代码发送数据,没出过问题。
if (window.XMLHttpRequest) { // Mozilla 浏览器 //新建XMLHttpRequest对象
xmlhttp = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE 浏览器
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) { }
}
}
var fd = new FormData();
var file = document.getElementById('filebox_file_id_1');
var fileList = file.files;
if (fileList.length != 0)
{
if (fileList[0].length / 1024 / 1024 > 20) {
alert("所选图片大小超出限制(20MB),无法上传!");
$('#fileToUpload').filebox('setValue', '');
return;
}
fd.append("fileToUpload", fileList[0]);
}
fd.append("data",JSON.stringify(jsondata));
xmlhttp.open("POST", "../api/Company/Register", true); //规定发送的类型,文件在服务器的位置,是否异步传送
xmlhttp.setRequestHeader("Content-Type", "multipart/form-data"); //POST方式需要的语句,形成表单
xmlhttp.send(fd);
JObject data = JObject.Parse(HttpContext.Current.Request["data"]);
HttpFileCollection files = HttpContext.Current.Request.Files;
这就很奇怪了,因为一般来说火狐的兼容性要比IE好。于是上FIDDLER抓包。
先看TextView,格式完全一致,后台取出的InputStream也是一样的。
火狐
-----------------------------22544859410221
Content-Disposition: form-data; name="data"
{"f_CompanyName":"9","f_CompanyCode":"9","f_CompanyLicense":"9","f_Remark":""}
-----------------------------22544859410221--
-----------------------------7e1346131e0382
Content-Disposition: form-data; name="data"
{"f_CompanyName":"9","f_CompanyCode":"9","f_CompanyLicense":"9","f_Remark":""}
-----------------------------7e1346131e0382--
比较一下请求头。
火狐
POST http://localhost:2629/api/Company/Register HTTP/1.1
Host: localhost:2629
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:54.0) Gecko/20100101 Firefox/54.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data
Referer: http://localhost:2629/Web_Page/Register.aspx
Content-Length: 221
Cookie: CurrentUICulture=zh-CN
Connection: keep-alive
POST http://localhost:2629/api/Company/Register HTTP/1.1
Accept: */*
Content-Type: multipart/form-data, multipart/form-data; boundary=---------------------------7e1346131e0382
Referer: http://localhost:2629/Web_Page/Register.aspx#
Accept-Language: zh-CN
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: localhost:2629
Content-Length: 219
Connection: Keep-Alive
Pragma: no-cache
知道原因以后在回头看代码,找到这么一句:
xmlhttp.setRequestHeader("Content-Type", "multipart/form-data"); //POST方式需要的语句,形成表单
分析浏览器生成的协议头可以发现,IE接受了代码中指定的内容类型,但是又把自己的类型追加了上去(似乎不影响解析),而火狐直接把代码中指定的类型拿来用了,所以缺了分隔符信息。
这次的问题提醒我,不管是网上还是之前的项目里扒来的代码都不要直接用,至少要做到能看懂,知道每条语句是什么意思,不然难免出现各种奇葩问题。