最近在写一个小系统的时候遇到了一个文件上传的问题需要支持文件继续选择后上传全部的内容。这里记录一下学习的过程,以备后面会再次遇到。以前遇到的文件上传一般是单文件上传或者通过设置input的属性
<input name="file[]" type="file" multiple>
在后台通过遍历$_FILES[]数组(PHP)来实现多文件上传,但是这都是一次选择的结果,如果选择某些文件后再次点击选择的文件,提交表单后只能看到最新选择的文件被上传成功。而不能实现先后选择的文件都被上传。
我们需要的情况如下图所示。
通过这个demo很容易想到把选择出来的文件作为一个数组给保存下来,集中放在一个面板去显示,还可以通过附带按钮进行删除操作。在最后选择完文件后集中上传,这样就可以实现继续选择的功能。
实现思路:获取file文件列表,将其储存在数组中,向后台传递,但是却不了解如何能够将数据传到后台,后台的接收流程又是怎样的。所以通过查找发现有一个html5新增的FormData可以进行表单的提交。具体的可以查看表单多文件上传,这篇文章不仅提供了FormData的使用,还分析了filelist对象的使用。非常感谢作者的帮助。在思路确定下来后,开始实现。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link href="css/bootstrap.css" rel="stylesheet" type="text/css">
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
</head>
<body>
<form name="form" id="form" method="post" enctype="multipart/form-data">
<input type="file" multiple id="filetest" name="file[]">
<div id="displaybord" style="border: #a6e1ec; "></div>
<input type="button" class="btn btn-success" id="uploadBtn" value="上传">
<p class="upload-tip" hidden="hidden">文件上传成功</p>
</form>
</body>
</html>
js具体实现相关功能
var curFiles = [];//文件数组,用来保存复制后的filelist对象
$("#filetest").change(function () {
var files = this.files;
if(files && files.length){
Array.prototype.push.apply(curFiles, files);//复制
}
//去除文件名相同的情况(上传列表中多次出现同一个文件)
for (var i = 0; i < curFiles.length - 1; i++) {
for (var j = 1; j < curFiles.length; j++) {
if (i != j) {
if (curFiles[i].name == curFiles[j].name) {
curFiles.splice(j, 1)
}
}
}
}
draw();
});
//显示面板
function draw() {
$("#displaybord").empty();
for(var j =0; j<curFiles.length;j++){
$('#displaybord').append("<span><span>"+curFiles[j].name+"</span><button id='id"+j+"' class='btn btn-primary' οnclick='del(this.id)'>删除</button></span><br>");
}
}
//删除功能
function del(id) {
var name = $("#"+id).prev().text();
console.log(name);
curFiles = curFiles.filter(function(file) {
return file.name !== name;
});
console.log(curFiles);
draw();
}
//上传功能的实现
$('#uploadBtn').click(function () {
if(curFiles.length>0){
var fd = new FormData($('#form'));
for (var i = 0; i<curFiles.length; i++) {
fd.append('myFileTest[]', curFiles[i]);//FormData上传
}
$.ajax({
url: 'fileTest.php',
type: 'post',
data: fd,
processData: false,
contentType: false,
success: function(rs) {
// console.log(rs);
rs = JSON.parse(rs);
$('.upload-tip')
.addClass('text-success')
.removeClass('text-error')
.text(rs.num + '个文件上传成功')
.attr('hidden',false);
$('#displaybord').empty();
},
error: function(err) {
}
});
}
else{
alert("请选择文件后上传");
}
});
后台接收列表(PHP处理)
$files = $_FILES['myFileTest'];
for ($i=0; $i < count($_FILES['myFileTest']['name']); $i++) {
move_uploaded_file($_FILES["myFileTest"]["tmp_name"][$i], "file/" . iconv("UTF-8","gbk//ignore",$_FILES["myFileTest"]["name"][$i]));
}
$arr = array('num'=>count($_FILES['myFileTest']['name']));
echo json_encode($arr);
结果列表如下图所示:
上面就是基本的实现过程,不过自己的水平有限,界面很不美观。只是记录下自己的学习过程。
最后,我还是选择了使用Fileinput插件,插件十分美观,不仅完美实现所需功能,还有很多更强大的功能,比如实时模拟上传进度、文件预览等,附一张最后的图。