这里将要实现一个,通过调用一个方法,弹出来一个上传文件框。
但如果仅仅只是弹出一个窗口,那就太没意义了。所以这个可通过一个对象参数,指定与哪个服务交互,文件是否可多选等。
定义该方法名称为createFormAndUpload,下面为调用该方法的例子
createFormAndUpload.call(window,{
method: 'put', //请求接口的方法
multiple: false, //表单可否多选
url: '/api/xxxxxx', //请求接口的url
on: {
submit: function(files,handle){
//选择文件之后 ,提供一个入口让使用者可以控制发送请求的时刻
},
finishedSubmit: function(files){}, //完成请求后
error: function(){},//出错的回调
}
})
关于参数的属性method、multiple、url都比较好理解,看注释即可。
这里着重说明on属性对象:
- submit
如果on对象使用该属性,发送请求的控制权完全交付给使用者,使用者必须调用handle方法才能发送请求。
为什么要这么做呢?在发送请求之前,或许你需要检查一下文件类型是否符合你的需求,然后再决定是否真的要发送请求 - finishedSubmit
这个属性是请求完成后,服务返回响应后的回调,使用者可以在这时候根据需要做处理 - error
该属性是请求完成后,服务返回错误的响应码,或者请求服务失败,使用的回调
那么下面就是实现方法的代码了:
function createFormAndUpload(ops){
var self = this;
var constantForm = 'createFormAndUpload_form',
constantInput = 'createFormAndUpload_input';
var fns = ops.on || {};
if(!Object.prototype.hasOwnProperty.call(self,constantForm)){
var form = document.createElement('form');
form.setAttribute('enctype','multipart/form-data')
form.style.display = 'none'
var _input = document.createElement('input')
_input.setAttribute('type','file')
_input.value = ''
ops.multiple && _input.setAttribute('multiple','multiple')
form.appendChild(_input)
document.body.appendChild(form);
self[constantForm] = form;
self[constantInput] = _input;
_input.click();
_input.addEventListener('change',function(e){
//点开文件选择框,如果之前_input的value不为'',点击'取消'则也触发change事件,此时长度为0
if(_input.files.length == 0) return;
if(fns.submit) fns.submit(_input.files,ajaxHandler)
else ajaxHandler()
function ajaxHandler(){
console.log('change');
var files = _input.files;
var finishedFlag = 0;
for(var i=0;i<files.length;i++){
var xhr = new XMLHttpRequest();
xhr.responseType = "json";
var formData = new FormData();
formData.append('upfile',files[i]);
xhr.open(ops.method,ops.url,true);
xhr.send(formData);
xhr.onload = function(e){
var data = this.response;
finishedFlag++;
if(data.error_code==200){
if(finishedFlag == files.length){
delete data.error_code;
fns.finishedSubmit && fns.finishedSubmit(files,data);
_input.value = '';
}
}else{
fns.error && fns.error(files)
}
}
xhr.onerror = function(e){
fns.error && fns.error(files)
}
xhr.ontimeout = function(e){
fns.error && fns.error(files)
}
}
}
})
}else{
self[constantInput].value = '';
self[constantInput].click();
}
}
涉及到跨域或者xhr设置的方面,请访问你真的会使用XMLHttpRequest吗?