前面介绍文件上传的文章,前端都是用的html自带的form和input标签选择并上传文件,其主要问题是看不到文件清单和上传进度,也无法删除部分待上传文件。很多前端ui框架提供了文件上传组件或服务,本文准备结合前端ui框架中,实现多文件上传功能
目前最流行的ui框架莫过于与vue配合最好的elementui,但学习该框架还得学vue,需要时间。除了该框架,在其它流行的ui框架中,本文选择使用Layui进行测试。
layui是一套开源的 Web UI 解决方案,采用自身经典的模块化规范,并遵循原生 HTML/CSS/JS 的开发方式,常适合网页界面的快速开发。虽然layui官网2021年10月下线,但其新版下载、文档和示例在内的所有框架日常维护工作,将全部迁移到 Github 和 Gitee。
参考文献1中提供有使用layui实现各种文件上传的前端示例,其中也包括多文件上传,支持显示待上传文件清单、显示上传进度、删除部分待上传文件。经测试,该部分示例可直接应用与之前的多文件上传mvc项目中,只要将其中的上传url修改为Home/UploadPhysical即可。下面代码为从layui示例中抽取的多文件上传相关的内容,该部分内容修改上传url后可直接使用。
<h1>MVC项目调用Layui上传文件</h1>
<<div class="layui-upload">
<button type="button" class="layui-btn layui-btn-normal" id="testList">选择多文件</button>
<div class="layui-upload-list">
<table class="layui-table">
<thead>
<th>文件名</th>
<th>大小</th>
<th>上传进度</th>
<th>操作</th>
</thead>
<tbody id="demoList"></tbody>
</table>
</div>
<button type="button" class="layui-btn" id="testListAction">开始上传</button>
</div>
@section Scripts {
<script>
layui.use(['upload', 'element'], function(){
var $ = layui.jquery
,upload = layui.upload
,element = layui.element;
//演示多文件列表
var demoListView = $('#demoList');
var uploadListIns = upload.render({
elem: '#testList'
,url: 'Home/UploadPhysical'
,accept: 'file'
,multiple: true
,number: 5
,auto: false
,bindAction: '#testListAction'
,choose: function(obj){
var files = this.files = obj.pushFile(); //将每次选择的文件追加到文件队列
//读取本地文件
obj.preview(function(index, file, result){
var tr = $(['<tr id="upload-'+ index +'">'
,'<td>'+ file.name +'</td>'
,'<td>'+ (file.size/1014).toFixed(1) +'kb</td>'
,'<td><div class="layui-progress" lay-filter="progress-'+ index +'"><div class="layui-progress-bar" lay-percent=""></div></div></td>'
,'<td>'
,'<button class="layui-btn layui-btn-xs demo-reload layui-hide">重传</button>'
,'<button class="layui-btn layui-btn-xs layui-btn-danger demo-delete">删除</button>'
,'</td>'
,'</tr>'].join(''));
//单个重传
tr.find('.demo-reload').on('click', function(){
obj.upload(index, file);
});
//删除
tr.find('.demo-delete').on('click', function(){
delete files[index]; //删除对应的文件
tr.remove();
uploadListIns.config.elem.next()[0].value = ''; //清空 input file 值,以免删除后出现同名文件不可选
});
demoListView.append(tr);
element.render('progress');
});
}
,done: function(res, index, upload){
//if(res.code == 0){ //上传成功
var tr = demoListView.find('tr#upload-'+ index)
,tds = tr.children();
tds.eq(3).html(''); //清空操作
delete this.files[index]; //删除文件队列已经上传成功的文件
return;
//}
this.error(index, upload);
}
,allDone: function(obj){
console.log(obj)
}
,error: function(index, upload){
var tr = demoListView.find('tr#upload-'+ index)
,tds = tr.children();
tds.eq(3).find('.demo-reload').removeClass('layui-hide'); //显示重传
}
,progress: function(n, elem, e, index){
console.log(n);
element.progress('progress-'+ index, n + '%'); //进度条
}
});
});
</script>
}
后端代码几乎没有变化,这里就不贴出来了,唯一需要说明的是,之前上传文件函数最后处的返回语句是下面的代码,这样返回的结果会跳转到前面JavaScript语句中的error处理部分:
public async Task<IActionResult> UploadPhysical()
{
...
...
return View("Index");
}
参照参考文献3,返回与前端约定好的数据结构,即可正常运行。本文中为简单起见,直接返回了个字符串。
public async Task<IActionResult> UploadPhysical()
{
...
...
return Json("OK");
}
最后是程序运行效果,如下图所示,选择多个文件,点击开始上传后,即可将所选文件全部上传到指定文件夹。
参考文献
[1]https://layui.gitee.io/v2/demo/
[2]https://github.com/layui/layui
[3]https://blog.csdn.net/weixin_43189545/article/details/109722105?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2aggregatepagefirst_rank_ecpm_v1~rank_v31_ecpm-7-109722105-null-null.pc_agg_new_rank&utm_term=asp.net%20core%20layui&spm=1000.2123.3001.4430