LayUI多檔案上傳,支援歷史上傳預覽

打不死的小強ღ發表於2024-01-17

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

提交表單

 

 

相關文章