js实现文件上传
四种常见的post数据类型
首先文件上传首先想到的发post,当然还有其他的上传协议,我们这里只介绍发post。
post支持四种content-type:
- application/x-www-form-urlencoded
Content-Type 被指定为 application/x-www-form-urlencoded;其次,提交的数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码。
- multipart/form-data
Request URL:http://192.168.13.11:8080/fetch2/test/test3
Request Method:POST
Status Code:200 OK
Request Headers:
Accept:*/*
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:6010
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryk0in9FHBncyu30RT
Host:192.168.13.11:8080
Origin:null
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
Request Payload
------WebKitFormBoundaryk0in9FHBncyu30RT
Content-Disposition: form-data; name="file1"; filename="main.cpp"
Content-Type: application/octet-stream
------WebKitFormBoundaryk0in9FHBncyu30RT--
首先生成了一个 boundary 用于分割不同的字段,为了避免与正文内容重复,boundary 很长很复杂。然后 Content-Type 里指明了数据是以 mutipart/form-data 来编码,本次请求的 boundary 是什么内容。消息主体里按照字段个数又分为多个结构类似的部分,每部分都是以 --boundary 开始,紧接着内容描述信息,然后是回车,最后是字段具体内容(文本或二进制)。如果传输的是文件,还要包含文件名和文件类型信息。消息主体最后以 --boundary-- 标示结束。
RFC1867
- application/json
application/json这个Content-Type都比较熟悉,当然也可以把json放到formData中;
RFC4657
- text/xml
参见RFC,也比较常见。
XML-RFC
实现文件上传有2种方式
- 普通post请求
该请求指的是content-type是application/json或text/xml,这种方式很简单,读取文件内容,然后上传即可,当然,有很多局限性; - 利用formdata
formdata文件上传是以二进制流形式上传,且无需写额外代码。
- 创建formdata:
//添加form标签
<form enctype="multipart/form-data" method="post" name="fileinfo" id="myFormElement">
</form>
//创建formdata
var formElement = document.getElementById("myFormElement");
formData = new FormData(formElement);
//若有其他元素不在表单里的,可以通过append添加
formData.append("bookid",$('#bookID'.val()));
- 使用formData发送文件
在HTML中要有一个包含了文件输入框的form元素,表单里元素的name一定要写,最终形成formData时,是以name作为key值
<form enctype="multipart/form-data" method="post" name="fileinfo">
<label>书名:</label>
<input type="text" name="bookname" /><br />
<label>bookid:</label>
<input type="text" name="bookid" /><br />
<label>File to stash:</label>
<input type="file" name="file" />
</form>
<div id="output"></div>
<a href="javascript:sendForm()">Stash the file!</a>
如果直接在form里写action的话,会刷新表单,同步请求。所以用发送异步post请求方式。
function sendForm() {
var oOutput = document.getElementById("output");
var oData = new FormData(document.forms.namedItem("fileinfo"));
//userName不在表单中
oData.append("userName", "lilei");
var oReq = new XMLHttpRequest();
oReq.open("POST", "stash.php", true);
oReq.onload = function(oEvent) {
if (oReq.status == 200) {
oOutput.innerHTML = "Uploaded!";
} else {
oOutput.innerHTML = "Error " + oReq.status + " occurred uploading your file.<br \/>";
}
};
oReq.send(oData);
}
你还可以不借助HTML表单,直接向FormData对象中添加一个File对象或者一个Blob对象:
data.append("myfile", myBlob);
你还可以使用jQuery来发送FormData,但必须要正确的设置相关选项:
var fd = new FormData(document.getElementById("fileinfo"));
//userName不在表单中
oData.append("userName", "lilei");
$.ajax({
url: "stash.php",
type: "POST",
data: fd,
processData: false, // 告诉jQuery不要去处理发送的数据
contentType: false // 告诉jQuery不要去设置Content-Type请求头
});
网友评论