Stories

Detail Return Return

LayUI多文件上傳,支持歷史上傳預覽 - Stories Detail

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

提交表單

 

 

Add a new Comments

Some HTML is okay.