這裏將要實現一個,通過調用一個方法,彈出來一個上傳文件框。
但如果僅僅只是彈出一個窗口,那就太沒意義了。所以這個可通過一個對象參數,指定與哪個服務交互,文件是否可多選等。
定義該方法名稱爲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嗎?