LayUI多文件上传,支持历史上传预览
记录一次项目开发中,LayUI多个图片进行优化,需要支持多个图片上传、可删除某一个图片、支持加载上次上次图片。
页面代码:
<div class="layui-upload">
<button type="button" class="layui-btn layui-btn-normal" id="ID-upload-demo-files">选择多文件</button> <div class="layui-upload-list">
<table class="layui-table">
<colgroup>
<col style="min-width: 100px;">
<col width="100">
<col width="150">
<col width="260">
<col width="100">
</colgroup>
<thead>
<th>图片</th>
<th>文件名</th>
<th>大小</th>
<th>上传进度</th>
<th>操作</th>
</thead>
@*历史数据*@
<tbody id="ID-upload-pre-files-list">
@{
var filelist = ViewData["UploadedList"] as List<MultiPics>;
if (filelist != null && filelist.Count > 0)
{
foreach (var file in filelist)
{
<tr id="fileList@((filelist.IndexOf(file)+1).ToString())">
<td>
<img src="@file.Content" class="tdPreImg">
</td>
<td>
<i class="del-img" id="@((filelist.IndexOf(file)+1).ToString())" data-src="@file.FilePath"></i>@file.FileName
</td>
<td>@file.FileSize KB</td>
<td>已上传</td>
<td>
@*因为layui按钮会提交,此处后台加载的图片,不用layui按钮*@
<input type="button" value="删除" class="btn_del" id="btn_del@((filelist.IndexOf(file)+1).ToString())" data-index="@((filelist.IndexOf(file)+1).ToString())" />
</td>
</tr>
}
}
}
</tbody>
@*当前上传*@
<tbody id="ID-upload-demo-files-list">
</tbody>
</table>
</div> <button type="button" class="layui-btn" id="ID-upload-demo-files-action">开始上传</button>
</div>
LayUI js 代码:
layui.use(function () {
var upload = layui.upload;
var element = layui.element;
var $ = layui.$;
var deliveryId = $("#LogID").val();
// 制作多文件上传表格
var uploadListIns = upload.render({
elem: '#ID-upload-demo-files',
elemList: $('#ID-upload-demo-files-list'), // 列表元素对象
url: '/Ship/OrderInfo/UploadImages?id=' + deliveryId,
accept: 'images',
multiple: true,
number: 10,
exts: "png|jpg|jpeg",
auto: false,
bindAction: '#ID-upload-demo-files-action',
choose: function (obj) {
var that = this;
// 将每次选择的文件追加到文件队列
var files = this.files = obj.pushFile();
// 读取本地文件
obj.preview(function (index, file, result) {
//console.log('choose' + index)
var tr = $(['<tr id="upload-' + index + '">',
'<td>'
+ '<img src=\'' + result + '\' class=\'tdPreImg\'>'
+ '</td>',
'<td>'
+ '<i class="del-img" id="del-'+index+'" data-src=""></i>'
+ file.name + '</td>',
'<td>' + (file.size / 1024).toFixed(1) + 'kb</td>',
'<td><div class="layui-progress" lay-filter="progress-demo-' + 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(); // 删除表格行
// 清空 input file 值,以免删除后出现同名文件不可选
uploadListIns.config.elem.next()[0].value = '';
});
that.elemList.append(tr);
element.render('progress'); // 渲染新加的进度条组件
});
},
done: function (res, index, upload) { // 成功的回调
//console.log('done' + index)
// 删除文件队列已经上传成功的文件【很重要防止之前的图片重复上传】
delete this.files[index];
var that = this;
var tr = that.elemList.find('tr#upload-' + index);
var tds = tr.children();
if (res.result) { //上传成功
$('#del-' + index).attr('data-src', res.data)
//清空操作
tds.eq(3).html('');
tds.eq(3).html('上传成功!');
}
else {
this.error(index, upload);
tds.eq(3).html('上传失败!');
//弹框显示错误信息
layer.msg("上传失败!" + res.msg);
//调试人员查看,暂时保留
console.log("上传失败!" + res.msg + "#" + res.data);
}
},
allDone: function (obj) { // 多文件上传完毕后的状态回调
console.log(obj);
},
error: function (index, upload) { // 错误回调
var that = this.elemList.find('tr#upload-' + index);
//console.log(that);
that.find(".demo-reload").removeClass('layui-hide');
},
progress: function (n, elem, e, index) {
element.progress('progress-demo-' + index, n + '%'); // 执行进度条。n 即为返回的进度百分比
}
});
});
页面加载数据和提交表单js
var main = {
@*初始化,静态js*@
Init: function () {
$(document).ready(function () {
@* Layui自带图片删除,历史图片的删除需特殊处理 *@
$(".btn_del").click(function () {
var _index = this.getAttribute("data-index");
var _tr = $("#fileList" + _index);
$("#ID-upload-pre-files-list")[0].removeChild(_tr[0]);
})
});
},
@* 获取参数,前台不提交文件,后台绑定 *@
SaveSignBack: function () {
@*图片地址列表*@
var _BackImage = "";
@*发货日志*@
var _ID = $("#LogID").val();
var _Note= $("#Note").val();
//图片提取并限制数量
var images_ids = $('.del-img');
@*限制上传图片数量*@
if (images_ids.length > 10) {
layer.msg("图片最多选择10张");
return false;
}
@*以|竖线分割,拼接字符串*@
if (images_ids.length) {
var images = '';
$.each(images_ids, function (index, val) {
if (images == '') {
images += $(val).attr('data-src')
} else {
images += '|' + $(val).attr('data-src')
}
});
//$(data.form).append('<input name="images" type="hidden" value="' + images + '">');//插入表单
//图片参数赋值
_BackImage= images;
}
@*获取表单内容序列化*@
//var fileForm = $("#form1").serialize();
//上传了图片,直接修改
if (_BackImage.length) {
main.FormSubmit(_LogID, _Note, _BackImage);
}
//未上传图片,弹框提示
else {
$.messager.confirm("提示", "您未上传图片,确定提交吗?", function (data) {
//确定
if (data) {
main.FormSubmit(_LogID, _Note, _BackImage);
return;
}
//修改,不处理
else { }
});
}
},
@* 提交后台 *@
FormSubmit: function (_LogID, _Note, _BackImage) {
$.post("/ControllerName/OrderInfo/BackSubmit",
{
LogID: _LogID,
Note: _Note,
Images: _BackImage
},
function (obj) {
if (obj.result) {
layer.msg(obj.msg);
//parent.refresh();
parent.location.reload();
parent.CloseWin();
}
else {
$.messager.alert('Info', obj.msg, 'info');
}
}
);
},
}
$(function () {
main.Init();
})
后台C#上传代码,表单提交后台代码就不贴了
public ActionResult UploadImages(int ID = 0)
{
////防止异常加载图片覆盖,延时半秒 SaveAs
//System.Threading.Thread.Sleep(500); try
{
#region 数据校验
//登录状态校验
if (CurrentUser.Id == 0)
{
return Json(new { result = false, msg = "登录失效!", data = "" });
} //获取回签单图片列表
HttpFileCollectionBase files = HttpContext.Request.Files;
//图片非空校验
if (files.Count == 0)
{
return Json(new { result = false, msg = "上传失败!请上传回签单图片!", data = "" });
} //单个图片轮询上传,只能单张上传
if (files.Count > 1)
{
return Json(new { result = false, msg = "参数错误!", data = "" });
}
#endregion //上传文件计数
var successCount = 0;
//图片相对路径(用于数据库保存)
string FilePath = string.Empty;
//循环保存图片,实际单个图片上传
for (int i = 0; i < files.Count; i++)
{
#region 拼接文件名(不含路径)
//文件类型
var fileType = string.Empty;
//获取文件类型
if (files[i].ContentType == "image/jpeg" || files[i].ContentType == "image/jpg")
{
fileType = ".jpg";
}
else if (files[i].ContentType == "image/png")
{
fileType = ".png";
} // 生成随机4位数字
var rand = (new Random()).Next(1000, 10000).ToString();
//文件名
var _name = ID + "_" + CurrentUser.Id + "_" + DateTime.Now.ToString("yyMMddHHmmsss") + "_" + rand;
//拼接文件名 回签图片名称格式:发货日志Id_上传人_年月日_4位随机数
var book = _name + fileType;
#endregion //获取配置文件的回签单保存路径 SignBackUrl
string savePath = System.Configuration.ConfigurationManager.AppSettings["FileUrl"];
//按月分文件夹
FilePath = DateTime.Now.ToString("yyyyMM") + "/" + book;
//文件完整路径
string fileFullPath = savePath + "/" + FilePath; //没有文件夹则创建
if (!Directory.Exists(savePath + "/" + DateTime.Now.ToString("yyyyMM")))
{
Directory.CreateDirectory(savePath + "/" + DateTime.Now.ToString("yyyyMM"));
} #region 文件大小校验
//保存图片到服务器上
files[i].SaveAs(fileFullPath); //创建文件 获取文件大小
var fileInfo = new FileInfo(fileFullPath);
//获取文件大小,单位KB 1KB=1024byte(字节)
decimal fileSize = (decimal)(fileInfo.Length > 0 ? (fileInfo.Length / 1024) : 0);
//2MB转成KB
var _2mb = (decimal)2 * 1024;
//获取大小异常
if (fileSize == 0)
{
//计算文件大小异常
return Json(new { result = false, msg = "计算文件大小异常 !", data = FilePath });
}
else if (fileSize != 0 && fileSize > _2mb)
{
//文件大小超出2MB
return Json(new { result = false, msg = "文件大小超出2MB,请修改后重试 !", data = FilePath });
}
#endregion//累计成功计数
successCount++;
} if (successCount == files.Count)
{
//成功返回,回调图片地址列表(相对地址)
return Json(new { result = true, msg = "上传成功 !", data = FilePath });
}
else
{
//失败
return Json(new { result = false, msg = "上传失败 !", data = "[上传文件数: " + successCount + "]" });
}
}
catch (Exception ex)
{
//抛出异常
return Json(new { result = false, msg = "上传异常,请重试 !", data = "[Exception: " + ex.Message + "]" });
}
}
上传图片时,出现上传图片名称和图片不能对应,数据串了问题。但是能想到可能是前一张图片没有保存,后面一张图片已经执行到保存方法,导致覆盖了。尝试了增加延时、后台记录id等一系列操作后,才发现是生成图片名称只到天。
后加了到秒并加了四位随机数,才得以解决。
Layui实际上是每上传一次图片,调用一次后台上传方法。
这里表格id " ID-upload-demo-files-list"是layui指定表格Id。已经上传的历史数据,不能用这个Id显示,单独加了一个tbody id="ID-upload-pre-files-list"用于显示已上传图片。需要删除,找到这行Dom移除即可。
提交表单

LayUI多文件上传,支持历史上传预览的更多相关文章
- .net core版 文件上传/ 支持批量上传,拖拽以及预览,bootstrap fileinput上传文件
asp.net mvc请移步 mvc文件上传支持批量上传,拖拽以及预览,文件内容校验 本篇内容主要解决.net core中文件上传的问题 开发环境:ubuntu+vscode 1.导入所需要的包:n ...
- java压缩包上传,解压,预览(利用editor.md和Jstree实现)和下载
java压缩包上传,解压,预览(利用editor.md和Jstree实现)和下载 实现功能:zip文件上传,后台自动解压,Jstree树目录(遍历文件),editor.md预览 采用Spring+Sp ...
- 使用java的 htpUrlConnection post请求 下载pdf文件,然后输出到页面进行预览和下载
使用java的 htpUrlConnection post请求 下载pdf文件,然后输出到页面进行预览和下载 2018年06月07日 10:42:26 守望dfdfdf 阅读数:235 标签: jav ...
- mvc文件上传支持批量上传,拖拽以及预览,文件内容校验等
使用bootstrap-fileinput 使用方式: 1.nuget:Install-Package bootstrap-fileinput 2.语言本地化{下载fileinput_locale_z ...
- 图片上传,支持同步/异步、预览(MVC、uploadify异步提交、js预览、ajaxSubmit异步提交)兼容大部分浏览器,含代码
图片上传代码,支持同步/异步和图片的预览 主要用了两种方式,可兼容大部分浏览器. 第一种使用uploadify异步上传,上传后返回图片路径显示到页面. 每二种使用ajaxSubmit异步上传,为兼容I ...
- ajax:html5上传文件,上传之前可以实现本地预览
本主题主要涉及两个新内容: 1.上传文件(主要使用了FormData) 2.本地预览(主要使用了FileReader) html5的FormData其实就是平时的Form表单,只是html5可以直接新 ...
- [java]文件上传下载删除与图片预览
图片预览 @GetMapping("/image") @ResponseBody public Result image(@RequestParam("imageName ...
- jQuery图片上传前先在本地预览(不经过后端处理)
前段时间遇到一个问题,前端想实现图片上传预览(不经过后端PHP或JAVA处理),用户点击file按钮上传文件,点击确定马上就能看到预览的效果,但在实现的时候无论怎样都取不到file上图片的真实路径,得 ...
- jQuery图片上传前先在本地预览
js代码: /* *名称:图片上传本地预览插件 v1.1 *作者:周祥 *时间:2013年11月26日 *介绍:基于JQUERY扩展,图片上传预览插件 目前兼容浏览器(IE 谷歌 火狐) 不支持saf ...
- JS实现上传本地图片前先预览
<style type="text/css"> #preview /*这个就是预览的DIV的ID*/ { filter:progid:DXImageTransform. ...
随机推荐
- 【Javaweb】implements Serializable是什么意思?反序列化是什么意思?
为了保证数据传输的可靠 性,常常要implements Serializable,为什么? 对象本质上是虚无缥缈的,只是内存中的一个地址,如果想要让对象持久化,让对象在网络上传输,总不可能传送一个内存 ...
- 运行tomcat之后报一个:"Address localhost:1099 is already in use"错误
一.解决方案 1.错误原因 "地址 localhost:1099 已在使用中",是1099程序被占用,把1099程序后台停止掉即可. 2.解决方案 1.快捷键win+R打开CMD运 ...
- 【scikit-learn基础】--『数据加载』之真实数据集
上一篇介绍了scikit-learn中的几个玩具数据集,本篇介绍scikit-learn提供的一些真实的数据集.玩具数据集:scikit-learn 基础(01)--『数据加载』之玩具数据集 1. 获 ...
- 吉特日化MES & SQL Server中的数据类型
一. 整数数据类型 1.bit bit数据类型是整型,其值只能是0.1或空值.这种数据类型用于存储只有两种可能值的数据,如Yes 或No.True 或False .On 或Off.注意:很省空间的一种 ...
- Mybatis-Flex核心功能之@Id
1.是什么? 在 Entity 类中,MyBatis-Flex 是使用 @Id 注解来标识主键的 2.怎么玩? public @interface Id { /** * ID 生成策略,默认为 non ...
- 华企盾DSC备用服务器无法启动,日志显示“主服务器停机超过十天”
出现该问题有三种情况: 1.主服务器未启动或授权到期: 2.主服务器申请的在线授权且ERP上存在到期的相同序列号: 3.备用服务器的数据库与主服务器连的不是同一个(检查IP和端口以及数据库名).
- 华企盾DSC导致wps个人模式无策略组新建的文件仍然加密
解决方法:右键wps安装目录手动解密即可(原因:wps模板被加密导致)
- 华企盾DSC控制台+系统运维模块连接不上问题
解决方法:把rundll32.exe进程结束之后再点系统运维模块
- 【Python】【OpenCV】定位条形码(二)moments和HuMoments
根据上一篇博客可知,单纯的通过求取最大面积而进行定位的局限性,因此我们接下来将通过cv2.moments()和cv2.HuMoments()这两个方法来在更复杂的环境中去找到我们的目标区域. cv2. ...
- 云MSP技本功|基于OGG 实现Oracle到Kafka增量数据实时同步
简介: 在大数据时代,存在大量基于数据的业务.数据需要在不同的系统之间流动.整合.通常,核心业务系统的数据存在OLTP数据库系统中,其它业务系统需要获取OLTP系统中的数据.传统的数仓通过批量数据同步 ...