$.ajax上传文件,contentType需设为false
开发遇坑,用$.ajax
上传文件,后台报错the request was rejected because no multipart,研究发现是$.ajax
里contentType设置有问题,不能直接设置为multipart/form-data
,而需要设为false
,具体看代码:
HTML部分:
<body>
<input type="text" name="id" id="id" value="" />
<input type="text" name="text" id="text" value="" />
<input type="file" multiple="multiple" id="files" name="files">
</body>
首先构建需上传的数据对象
var files = $('#files')[0].files;
var imgFiles = [];
for (var i = 0; i < files.length; i++) {
var file = files[i];
//保存文件到数组
imgFiles.push(file);
}
var obj = {
id:$("#id").val(),
text:$("#text").val(),
files:imgFiles
}
将数据对象转换为formData:
var fromData = new FormData();
$.each(obj,function(key,value) {
fromData.append(key,value);
})
最后使用$.ajax提交:
$.ajax({
type: 'post',
url: 'url',
cache: false,
contentType: "multipart/form-data",
processData: false, //默认为true,默认情况下,发送的数据将被转换为对象,设为false不希望进行转换
data: fromData, //数据
success: function(data, textStatus, jqXHR) {
console.log("请求返回success信息data:", data);
}
});
此时后台会报错:the request was rejected because no multipart
F12查看network一栏的请求信息,发现contentType设置成功,但还是会报错:
为什么会报错呢?我们先把$.ajax里的contentType设为false
,再次发送请求:
$.ajax({
type: 'post',
url: 'url',
cache: false,
contentType: false,
processData: false, //默认为true,默认情况下,发送的数据将被转换为对象,设为false不希望进行转换
data: fromData, //数据
success: function(data, textStatus, jqXHR) {
console.log("请求返回success信息data:", data);
}
});
请求成功,查看network的请求信息:
发现成功时比失败时contentType多了一串boundary+一串字符,后面的一堆字符串是随机生成的,目的是防止上传文件中出现分界符导致服务器无法正确识别文件起始位置。
在 ajax 中 contentType 设置为 false 是为了避免 JQuery 对其操作,从而失去分界符,而使服务器不能正常解析文件。
如果不用$.ajax
,而是使用原生form提交,将form表单的enctype设为"multipart/form-data"也能正常提交到服务器(form的"multipart/form-data"是将文件以二进制的形式上传,这样可以实现多种类型的文件上传)
<form action="" method="post" enctype="multipart/form-data">
<input type="text" name="id" id="id" value="" />
<input type="file" multiple="multiple" id="files" name="files">
<input type="submit" value=""/>
</form>
总结:
- 发送带file的form请求,将form表单的enctype设为"multipart/form-data"可以实现;
- 如果使用
$.ajax
发送请求,则需要将配置项contentType设为false
,而不能直接设置为"multipart/form-data",后者发送的请求在Request headers的contentType中没有分界符,会导致后台无法解析并报错。 - multipart/form-data 请求是基于 http 原有的请求方式 post 而来的,multipart/form-data 请求与 post 的区别是:
- 请求头的不同,对于上传文件的请求,contentType = multipart/form-data是必须的,而 post 则不是,毕竟 post 又不是只上传文件。
- 请求体不同。这里的不同也就是指前者在发送的每个字段内容之间必须要使用分界符来隔开,比如文件的内容和文本的内容就需要分隔开,不然服务器就没有办法正常的解析文件,而后者 post 当然就没有分界符直接以 name = "value"的形似发送。
本文参考: