記錄一次專案開發中,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.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移除即可。
提交表單