文件上傳在網頁應用中應該是一個很常用的功能,但是我是第一次做,所以也是網上找資料了,看了如阮一峰老師的《文件上傳的漸進式增強》對文件上傳有了大概的了解,結合自己的知識改寫了一個文件上傳工具共享給大家,包含了我在過程中遇到的坑~。
先上圖
上代碼
myUpload(option) {
va rfd =newFormData(),
xhr =newXMLHttpRequest(),
input,per;
input =document.createElement('input');
input.setAttribute('id','myUploadInput');
input.setAttribute('type','file');
input.setAttribute('name','files');
// input.setAttribute('accept','image/*')
document.body.appendChild(input);
input.style.display='none';
使用FormData仿真fram表結構,創建input按鈕來上傳文件,為了避免重復重復創建input標簽修改代碼如下
myUpload(option) {
varfd =newFormData(),
xhr =newXMLHttpRequest(),
input,loaded,total,per;
if(document.getElementById('myUploadInput')){
input =document.getElementById('myUploadInput');
}else{
input =document.createElement('input');
input.setAttribute('id','myUploadInput');
input.setAttribute('type','file');
input.setAttribute('name','files');
// input.setAttribute('accept','image/*')
document.body.appendChild(input);
input.style.display='none';
}
在上邊代碼中有一行被注釋的代碼
// input.setAttribute('accept','image/*')
我想控制只能上傳圖片,但帶來一個很大延遲反應是,點擊了圖片上傳功能后過了3,4秒才彈出文件上傳框,而且用戶還能修改文件上傳格式,這個方法行不通。所以最后通過js代碼控制了文件上傳格式,看如下代碼
varfileType = ['jpg','png','bmp','jpeg'];
vartype = input.value.split('.').pop();
if(fileType.indexOf(type.toLocaleLowerCase()) == -1) {
alert('只支持(jpg,png,bmp,jpeg)后綴文件');
}
通過input的onchange事件響應文件上傳
input.click();
input.onchange=function() {
if(!input.value) {
return;
}
varfileType = ['jpg','png','bmp','jpeg'];
vartype = input.value.split('.').pop();
if(fileType.indexOf(type.toLocaleLowerCase()) == -1) {
alert('只支持(jpg,png,bmp,jpeg)后綴文件');
}
if(option.maxSize&& input.files[0].size> option.maxSize*1024*1024) {
alert('請上傳小于'+option.maxSize+'M的文件');
return;
}
if(option.beforeSendinstanceofFunction) {
if(option.beforeSend(input) ===false) {
return false;
}
}
fd.append('files',input.files[0]);
xhr.onreadystatechange=function() {
if(xhr.status==200) {
if(xhr.readyState==4) {
if(option.callbackinstanceofFunction) {
option.callback(xhr.responseText);
}
}
}else if(xhr.status!=200){
alert('上傳失敗')
}
}
xhr.upload.onprogress=function(event) {
varpre =Math.floor(100* event.loaded / event.total);
if(option.uploadinginstanceofFunction) {
option.uploading(pre);
}
console.log('onprogress loaded'+ event.loaded );
console.log('onprogress total'+ event.total);
console.log('onprogress'+ pre);
}
xhr.open('post',option.url);
xhr.send(fd);
}
}
上邊代碼有幾個坑,
兼容性問題
其一,FormData不支持IE11以下版本的瀏覽器(大家按需求引用)
其二,在IE瀏覽器中會出現,文件上傳會出現點一次點擊沒有上傳文件,再次點擊才上傳文件。出現的原因可能是input呼出文件上傳框中斷了input onchange事件。代碼修改如下
input.onchange=function() {
if(!input.value) {
return;
}
varfileType = ['jpg','png','bmp','jpeg'];
vartype = input.value.split('.').pop();
if(fileType.indexOf(type.toLocaleLowerCase()) == -1) {
alert('只支持(jpg,png,bmp,jpeg)后綴文件');
}
if(option.maxSize&& input.files[0].size> option.maxSize*1024*1024) {
alert('請上傳小于'+option.maxSize+'M的文件');
return;
}
if(option.beforeSendinstanceofFunction) {
if(option.beforeSend(input) ===false) {
return false;
}
}
fd.append('files',input.files[0]);
xhr.onreadystatechange=function() {
if(xhr.status==200) {
if(xhr.readyState==4) {
if(option.callbackinstanceofFunction) {
option.callback(xhr.responseText);
}
}
}else if(xhr.status!=200){
alert('上傳失敗')
}
}
xhr.upload.onprogress=function(event) {
varpre =Math.floor(100* event.loaded / event.total);
if(option.uploadinginstanceofFunction) {
option.uploading(pre);
}
console.log('onprogress loaded'+ event.loaded );
console.log('onprogress total'+ event.total);
console.log('onprogress'+ pre);
}
xhr.open('post',option.url);
xhr.send(fd);
}
input.click();
}
此時還有一個問題是每次上傳文件都會有alert提示alert('上傳失敗')
else if(xhr.status!=200&& xhr.readyState==4){
alert('上傳失敗')
}
/*
0 (未初始化): (XMLHttpRequest)對象已經創建,但還沒有調用open()方法。
1 (載入):已經調用open() 方法,但尚未發送請求。
2 (載入完成): 請求已經發送完成。
3 (交互):可以接收到部分響應數據。
4 (完成):已經接收到了全部數據,并且連接已經關閉。
* */
?方法的調用的調用
在目標文件中申明 var uploadTool = requilre('./uploadTool');
uploadTo0l.myUpload({
url:文件上傳路徑',
maxSize:2,
beforeSend:function(file) {
console.log('beforeSendLogo'+ file);
},
callback:function(res) {
vardata =JSON.parse(res);
上傳回調
}
},
uploading:function(pre) {
console.log('logo'+ pre);
上傳進度
},
});
代碼寫完了,在IE11中,chrom,火狐,360都可以用。