先上效果图:
点击x可以删除文件,也可以继续添加文件,已添加文件还在,不会消失,主要还是js事件控制的。
html:
<label class="top" title="支持上传格式:jpg/jepg/png/doc/docx/xls/xlsx/pdf/mp4/mp3/avl/flv/zip/rar">上传文件
<input type="file" id="btnAdd" name="btnAdd" style="display: none" multiple="multiple"
onchange="CustTouchAuditing.uploadChange()"/></label>
<span id="addFileBtnSpan"></span>
css:
.top {
height: 30px;
width: 80px;
background-color: dodgerblue;
font-size: 14px;
line-height: 30px;
cursor: pointer;
display: inline-block;
text-align: center;
color: #fff;
border-radius: 5px;
border: 1px solid #666666;
}
.topFile {
height: 30px;
width: 95px;
background-color: floralwhite;
font-size: 14px;
line-height: 30px;
cursor: pointer;
display: inline-block;
text-align: center;
border-radius: 5px;
margin-left: 15px;
}
js 代码(DWR框架)
// 附加上传文件集合
var forDateTempList = [];
// 附件上传文件名集合,用来判断是否重复上传文件
var fileNameList = [];
// 附加上传文件个数
var tempI = 0;
CustTouchAuditing.uploadChange = function () {
// 校验文件大小
if (!checkFile()) {
return
}
// 要追加生成的html,也就是那些带文件名字的框
var appendHtml = '';
// 已经存在的文件的文件名
let errorFile = '';
// file对象
var input = document.getElementById("btnAdd");
for (var i = 0; i < input.files.length; i++) {
let fileName = input.files[i].name;
// 判断当前选择的文件是否已经选择
if (fileNameList.indexOf(fileName) < 0) {
fileNameList.push(fileName)
// file类型无法存到对象,使用FormData进行封装,我使用一个FormData封装一个文件
var forDateTemp = new FormData();
forDateTemp.append('file', input.files[i]);
forDateTempList.push(forDateTemp);
// 这边的slice截取是为了只显示文件部分名字,看个人需求
appendHtml += '<label id="addFileBtn' + tempI + '" class="topFile">' +
'<span id="addFileName">' + fileName.slice(0, 5) + '</span>' +
'<span aria-hidden="true" style="float: right;line-height: 7px;">' +
'<a onclick="CustTouchAuditing.deleteFileBtn(' + tempI + ')">x</a>' + '</span></label>';
tempI++
} else {
// 已经存在的文件名
errorFile += fileName + ",";
}
}
if (errorFile.length > 0) {
alert(errorFile + "等已添加,不可重复添加文件");
}
$("#addFileBtnSpan").append(appendHtml)
}
删除事件:这里使用splice把数组对应位置的置为null,为什么我这里这么写?因为,这里我使用使用数组去存每个新增的文件,这里就会产生一个问题,如果我删除第一个文件,然后再新增一个文件,数组中i位置对应的文件就会改变。
// 删除不想上传的文件
CustTouchAuditing.deleteFileBtn = function (i) {
$("#addFileBtn" + i).remove();
forDateTempList.splice(i,1,null);
fileNameList.splice(i,1,null);
}
上传附件:
var uploadRtn = '';
var uploadUrl = '';
// 判断是否存在文件
if(forDateTempList.length > 0){
// 获得附件上传地址,这里dwr框架调用后代,可以根据需求修改
CustContactImpl.queryUploadUrl( {
callback: function (ret) {
if (ret.result != null){
uploadUrl = ret.result;
}
}, async: false
});
// 循环多文件上传
for (var i = 0; i < forDateTempList.length; i++) {
// 这里就跟上面我把数组对应位置置null有关系,null就不去读,由于我这里的后台接口不能接受多
// 文件同时上传,所以我使用循环单文件上传的方式,可根据服务端接口,修改直接调用多文件传送一次
if (forDateTempList[i] != null) {
$.ajax({
method: 'POST',
cache: false,
async: false,
processData: false,
contentType: false,
mimeType: "multipart/form-data",
url: uploadUrl,
data: forDateTempList[i],
success: function (datas) {
uploadRtn += JSON.parse(datas).data;
},
error: function (datas) {
console.log(datas);
}
});
}
}
}
附上检验文件大小 ,仅供参考。
// 判断文件大小
function checkFile() {
try {
var fileMaxSize = Common.uploadFileSize() / 1048576;
var target = document.getElementById("btnAdd");
var checkFlag = true;
var fileSize = 0;
//ie判断逻辑
if (Common.isIE() && !target.files) {
try {
var filePath = target.value;
var fileSystem = new ActiveXObject("Scripting.FileSystemObject");
var file = fileSystem.GetFile(filePath);
fileSize = file.size;
} catch (ex) {
alert("您对脚本执行进行了否定,IE浏览器需进行相关配置!");
checkFlag = false;
return checkFlag;
}
} else {
fileSize = target.files[0].size;
}
var size = fileSize / 1048576;
if (size > fileMaxSize) {
alert("附件不能大于" + fileMaxSize + "M");
checkFlag = false;
return checkFlag;
}
if (size <= 0) {
alert("附件大小不能为0M!");
target.value = "";
checkFlag = false;
}
} catch (e) {
checkFlag = false;
return checkFlag;
}
return checkFlag;
}
有更好方式,欢迎交流。