之前在Vue的项目里面用到过文件上传,封装好的组件用起来比较顺手,查询Element-UI文档,十八般武器样样都有,一顿操作猛如虎,一看……跑偏了(⊙o⊙)…,我的意思就是用框架实现比较简单,但是如果用jQuery的话,对原理可能会更了解一些,有需要的一起看下吧~
1. multipart/form-data
因为HTTP提供的是基于文本的通信协议,而上传文件传输的是二进制数据,所以需要使用multipart/form-data
编码格式,其HTTP消息体格式如下:
------WebKitFormBoundaryb0GZcypmEqOvNHIY
Content-Deiposition: form-data; name="file"; filename="icon.png"
Content-Type: image/png
------WebKitFormBoundaryb0GZcypmEqOvNHIY
multipart/form-data
的请求头包含一个特殊的头信息Content-Type,其值为multipart/form-data,另外需要规定一个内容分割boundary用于分割请求体中多个不同的内容:
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryb0GZcypmEqOvNHIY
2. input选择并获取文件
<form>
<input type="file" id="uplfile" name="uplfile"/>
<button type="button" id="uplfileBtn">上传</button>
</form>
<form>
<input type="file" id="uplfile" name="uplfile"/>
<button type="button" id="uplfileBtn">上传</button>
</form>
type="file"
的input有一个叫files
的DOM属性,可以获取到所选的文件列表(Array),数组中每一个对象都是file类型,
var files = $("#uplfile").prop('files');
var files = $("#uplfile").prop('files');
3. jQuery上传文件
新版本的XMLHttpRequest对象可以使用FormData
对象管理表单数据,可以帮我们进行二进制文件的multipart/form-data编码,如下:
$("#uplfileBtn").click(function(){
var files = $("#uplfile").prop('files');
var data = new FormData();
data.append('file', files[0]); //参数名:file
$.ajax({
url: URL,
type: 'POST',
data: data,
cache: false, //禁止浏览器对该URL的缓存
contentType: false,
processData: false,
success: function(){
//后续操作
}
});
});
$("#uplfileBtn").click(function(){
var files = $("#uplfile").prop('files');
var data = new FormData();
data.append('file', files[0]); //参数名:file
$.ajax({
url: URL,
type: 'POST',
data: data,
cache: false, //禁止浏览器对该URL的缓存
contentType: false,
processData: false,
success: function(){
//后续操作
}
});
});
contentType
:jQuery中contentType默认为application/x-www-form-urlencoded
,因此传入的data会被转为默认的HTTP编码,这里我们不需要这种转换,设置为false。
processData
:jQuery会将传入的data对象转为字符串来发送HTTP请求,这里我们的data已经是FormData对象处理好的multipart/form-data编码,所以不需要转换,设置为false。
4. js中如何直接下载文件
通常在web前端需要下载服务端文件,都是通过指定<a>
标签的href属性访问服务端URL来下载保存文件的,也可以在js中:
document.location.href = Url + '?fileName=' + value;
document.location.href = Url + '?fileName=' + value;
上面这种方法用的是HTTP的GET请求,只能通过URL传参,在相对复杂的场景中(需要传多个参数在服务端动态下载指定文件),即参数比较多的时候,我们想要能够通过ajaxPOST
方式来传递参数。
但是用ajax请求的数据只能存放在JavaScript的内存中,可以通过js读取,无法保存到硬盘,因为JavaScript本身无法直接和硬盘交互。那么有什么方法可以实现呢?一向方法总比困难多,我们可以通过模拟Form表单的提交来实现POST请求下载文件,如下:
<form id="myform" action="http://blog.kwin.wang/test/xxx.do" method="post">
<input type="hidden" name="type" value="trade"/>
<input type="hidden" name="time" value="20180818"/>
<input type="hidden" name="fileName" value="a.png"/>
</form>
<form id="myform" action="http://blog.kwin.wang/test/xxx.do" method="post">
<input type="hidden" name="type" value="trade"/>
<input type="hidden" name="time" value="20180818"/>
<input type="hidden" name="fileName" value="a.png"/>
</form>
主动提交Form表单:
$("#myform")[0].submit();
$("#myform")[0].submit();