最近公司需求,实现文件上传,多文件上传,显示进度条。
首先可以使用各种文件上传的插件,但是,上传显示的列表样式不太好控制,一般都是弹框显示列表或者直接在某个div 中显示列表,如果需求对样式不太有要求,完全可以使用,这里就不再多说。
但是如果要求必须在页面的某一块显示,并且显示列表的样式就需要自己写了,这里不使用插件,直接使用jquery ajax进行文件上传,多文件上传,并且要显示进度条,支持取消上传功能;
基本思路是,
1.在点击选择文件时,首先拼接显示列表,并且显示进度条等
2.根据文件名称不同,对每一条显示数据进行编号,(这里可以使用MD5工具对文件名进行处理)
3.执行文件上传操作,上传完成后清除不需要显示的样式
4.关于重新上传,首先要对上传失败的文件进行记录,把它放到一个 formData 中,再次重新上传时,通过文件名 从中进行读取,然后执行上传方法即可。
代码如下:
var strName=$(_this).parent().attr("data-name");
//取出当前的file
var files = formAll.getAll("file");
var formdd =new FormData();
formdd.append("classify_id", $("#classify_id").val());
formdd.append("dir", $("#currentDir").val());
var labels = $("input[name^='labelId_']:checked");
for (var i = 0; i < labels.length; i++) {
formdd.append("labelIdList", $(labels[i]).val());
}
var tops = $("input[name^='topic_id']:checked");
for (var i = 0; i < tops.length; i++) {
formdd.append("topic_id", $(tops[i]).val());
}
//这边是比对 根据文件名 比对出需要重新上传的文件
for(var i in files){
if(files[i].name.split(".")[0]==strName){
formdd.append("file",files[i]) ;
break;
}
}
5.针对于多文件上传,我的操作还是通过循环formData里的file,通过ajax异步进行上传,因为这里要求是同时将上传的文件显示在列表上,如果没有页面要求,可以直接将formData中的所有file传到后台,然后后台再循环进行上传操作就可以
6.重点:取消ajax上传操作问题,当只是单个的文件上传时,直接调用 ajax的 .abort() 方法即可,如下:
var requestAjax = null;
function startAjax(){
//方法就是将XHR对象指向currentAjax,再调用currentAjax的.abort()来中止请求
requestAjax = $.ajax({
type:'POST',
beforeSend:function(){},
url:'test.PHP',
data:'username=xxx',
dataType:'JSON',
error:function(){alert('error')},
success:function(data){alert(data)}
});
}
function stopAjax(){
//如若上一次AJAX请求未完成,则中止请求
if(requestAjax ) {requestAjax .abort();}
}
但是当多文件循环上传时,ajax异步同时发起多个请求,这里就不能直接操作 requestAjax .abort(),因为你不知道当前的ajax是哪一个,实现思路是,将每一个ajax请求,放入到一个 map中,map的key就是文件名,值就是当前的这个ajax,读取的时候再根据文件名读取,然后继续调用.abort() 方法即可。
直接上代码:
//这里是上传提交方法
//确定按钮 提交内容数据 和上传的数据
var form = new FormData();//全局变量可以支持多次选择
$('#files-open-bottom_sure').click(function() {
resetFlag=2;
offFlag=2;
if ($('#file').val() == '') {
toastr.warning("请选择文件再上传");
} else {
if(form.get('file')==null){
toastr.warning("请选择文件再上传");
return false;
}
//隐藏弹框
$("#files_open").hide();
form.append("classify_id", $("#classify_id").val());
form.append("dir", $("#currentDir").val());
formAll.append("classify_id", $("#classify_id").val());
formAll.append("dir", $("#currentDir").val());
var labels = $("input[name^='labelId_']:checked");
for (var i = 0; i < labels.length; i++) {
form.append("labelIdList", $(labels[i]).val());
formAll.append("labelIdList", $(labels[i]).val());
}
var tops = $("input[name^='topic_id']:checked");
for (var i = 0; i < tops.length; i++) {
form.append("topic_id", $(tops[i]).val());
formAll.append("topic_id", $(tops[i]).val());
}
//for (var i = 0; i < $("#file")[0].files.length; i++) {
// form.append("file", $("#file")[0].files[i]);
//}
//获取form中的file
var formfile= form.getAll("file");
//循环提交 循环修改进度条
for(var i in formfile) {
form.delete("file");
form.append("file", formfile[i]);
formAll.append("file", formfile[i]);
var vname = formfile[i].name;
//这里是一个上传方法
ajaxSubmit(form,vname);
}
}
});
//上传方法
var requestAjax;
var ajaxList = new Array();
var map = {};
function ajaxSubmit(formData,name){
var strName = name.split(".")[0];
/*if (strName.indexOf(" ") != -1) {
toastr.error("上传失败!文件名不能有空格");
setTimeout("location.reload()",3000);
return false;
}*/
//获取文件的后缀名
var startIndex = name.lastIndexOf(".");
var ss =name.substring(startIndex+1, name.length);
if(ss.trim() !="mp4" && ss.trim() !="docx" && ss.trim() !="doc"&& ss.trim() !="pdf" && ss.trim() !="ppt"&& ss.trim() !="pptx"){
toastr.error("上传失败!只支持上传,视频格式:Mp4,文档格式:Word、PDF、PPT、pptx");
form=new FormData();
zlList.load();
return false;
}
strName=$.md5(strName);
$('#progress_'+strName+'> div ').css('width','');
toastr.info("上传中,请稍后!");
requestAjax = $.ajax({
url: "<%=request.getContextPath() %>/ps/file/upload.action",
type: "post",
data: formData,
cache: false,
processData: false,
contentType: false,
xhr: function () {
/*var xhr = new XMLHttpRequest();
//使用XMLHttpRequest.upload监听上传过程,注册progress事件,打印回调函数中的event事件
xhr.upload.addEventListener('progress', function (e) {
debugger
console.log(e);
//loaded代表上传了多少
//total代表总数为多少
var progressRate = (e.loaded / e.total) * 100 + '%';
//通过设置进度条的宽度达到效果
$('#progress_'+strName+'> div ').css('width', progressRate);
})
return xhr;*/
var xhr = $.ajaxSettings.xhr();
if (xhr.upload) {
xhr.upload.addEventListener("progress", function (evt) {
var loaded = evt.loaded;
var total = evt.total;
var percent = Math.floor(100*loaded/total);//百分比
if (percent<=99){
$('.percent').text(percent+"%");//数显进度
$('.fail-reroad-progress').css("width",percent+"%");
}
var progressRate = Math.floor((loaded / total)* 100) + '%';
//通过设置进度条的宽度达到效果
$('#progress_'+strName+'> div ').css('width', progressRate);
//显示上传数值
$('#jdNum_'+strName+'').text(progressRate);
}, false);
return xhr;
}
},
success: function (data) {
//$("#files_open").hide();
//hideMask();
if (data != "success") {
//显示重新上传
$('#progress_text_set_'+strName+'').show();
//显示删除 隐藏取消
$('#del_'+strName+'').show();
$('#off_'+strName+'').hide();
toastr.error("上传失败!");
$('.percent').text("上传失败");
$('.fail-reroad').css("color","red");
$('.files-open-upright-row-a3').css("color","red");
form = new FormData();//清空form,避免重复上传
} else {
$('#progressBox_'+strName+'').remove();
//进度条清空 隐藏
//$('#progress_'+strName+'> div ').css('width','');
// $('#progress_'+strName+'').hide();
//隐藏上传数值
// $('#jdNum_'+strName+'').parent().hide();
// zlList.load();
//修改上传列表的height
$('#subfiles_'+strName+'').find(".m-table-td").eq(0).css("height","55px");
toastr.success("上传成功!");
$('.percent').text("100%");
$('.fail-reroad-progress').css("width","100%");
form = new FormData();//清空form,避免重复上传
}
},
error: function () {
if(offFlag!=1){
toastr.error("上传失败!");
}
//显示重新上传
$('#progress_text_set_'+strName+'').show();
//显示删除 隐藏取消
$('#del_'+strName+'').show();
$('#off_'+strName+'').hide();
//进度条清空
// $('.progress > div').css('width','');
// $('.progress ').hide();
// hideMask();
// zlList.load();
$('.percent').text("上传失败");
$('.fail-reroad').css("color","red");
$('.files-open-upright-row-a3').css("color","red");
form = new FormData();//清空form,避免重复上传
}
});
map[strName] = requestAjax;
ajaxList.push(map);
}
//取消上传 取消标志
var offFlag;
function offUpload(keyname){
offFlag=1;
if(resetFlag!=1){
map[keyname].abort();
}else{
resetupload.abort();
}
}