异步上传文件,在很多场景中都有应用。本文介绍一种通过xhr和formdata实现的方法。
FormData属于h5的内容所以,浏览器兼容不是很好,下面是一种polyfill,inspired by francois2metz/html5-formdata
(function(w) {
if (w.FormData)
return;
function FormData() {
this.boundary = "--------FormData" + Math.random();
this._fields = [];
}
FormData.prototype.append = function(key, value) {
this._fields.push([key, value]);
}
FormData.prototype.toString = function() {
var boundary = this.boundary;
var body = "";
this._fields.forEach(function(field) {
body += "--" + boundary + "\r\n";
// file upload
if (field[1].name) {
var file = field[1];
body += "Content-Disposition: form-data; name=\""+ field[0] +"\"; filename=\""+ file.name +"\"\r\n";
body += "Content-Type: "+ file.type +"\r\n\r\n";
body += file.getAsBinary() + "\r\n";
} else {
body += "Content-Disposition: form-data; name=\""+ field[0] +"\";\r\n\r\n";
body += field[1] + "\r\n";
}
});
body += "--" + boundary +"--";
return body;
}
w.FormData = FormData;
var _send = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(data) {
if (data instanceof FormData) {
xhr.setRequestHeader("Content-Type", "multipart/form-data;boundary="+ data.boundary);
return xhr.sendAsBinary(data.toString());
}
return _send.call(this, data);
};
})(window);
像这样使用
var data = new FormData();
data.append('file', document.getElementById('file').files[0]);
xhr.open('POST', '/', true);
xhr.onprogress = (function(){
var progress = 0;
return function(evt){
var p = ~~(evt.loaded*1000/evt.total)
p /= 1000
if(progress !=== p){
progress = p
console.log('progress: ', p)
}
}
})();
关于兼容性,只要支持FieApi
就没问题