文件上传在网页应用中应该是一个很常用的功能,但是我是第一次做,所以也是网上找资料了,看了如阮一峰老师的《文件上传的渐进式增强》对文件上传有了大概的了解,结合自己的知识改写了一个文件上传工具共享给大家,包含了我在过程中遇到的坑~。
先上图
上代码
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都可以用。