第六節:基於LayUI組件的文件上傳 和 基於dropzonejs的文件上傳


一. 接口設計

1. 說明

 設計異步方法,這里采用文件流的形式進行存儲,設計兩個接口,分別用來處理單文件上傳和多文件上傳.

2. 大致思路

 獲取文件→判空→獲取文件名和擴展名→設置存放絕對路徑(若不存在,則新建)→編輯文件保存名稱(這里隨機命名,所以不用判重) →拼接最終路徑進行保存→DB中存儲相對路徑→返回前端成功和相對路徑.

3. 其它

 可以通過 .Length,來獲取文件的大小

代碼分享: 

        #region 01-單文件上傳
        /// <summary>
        /// 單文件上傳
        /// </summary>
        /// <param name="_hostingEnvironment"></param>
        /// <returns></returns>
        public async Task<IActionResult> SingleSaveFile([FromServices] IWebHostEnvironment _hostingEnvironment)
        {
            try
            {
                long size = 0;   //統計上傳文件的大小(單位b)
                var files = Request.Form.Files;  //獲取文件
                if (files.Count == 0)
                {
                    return Json(new { status = "error", msg = "上傳內容為空", data = "" });
                }

                //獲取文件擴展名
                var fileName = files[0].FileName;
                int idxStart = fileName.LastIndexOf(".");
                string areviation = fileName.Substring(idxStart, fileName.Length - idxStart);

                //編輯文件的存儲路徑
                var filePath = _hostingEnvironment.ContentRootPath + @"\DownLoad\Picture\";
                if (!Directory.Exists(filePath))
                {
                    Directory.CreateDirectory(filePath);
                }
                //編輯文件的名稱(目前是隨機命名,如果用原名保存,需要判重)
                var myFileName = $"{Guid.NewGuid().ToString()}{areviation}";
                //最終路徑
                var finalPath = filePath + myFileName;
                size += files[0].Length;
                using (FileStream fs = System.IO.File.Create(finalPath))
                {
                    await files[0].CopyToAsync(fs);
                    await fs.FlushAsync();
                }

                //DB中存儲的或者返回給前端的都是相對路徑
                string relativeUrl = $"/DownLoad/Picture/{myFileName}";

                return Json(new { status = "ok", msg = "上傳成功", data = relativeUrl });
            }
            catch (Exception ex)
            {
                return Json(new { status = "error", msg = "上傳失敗", data = "" });
            };
        }
        #endregion

        #region 02-多文件上傳
        /// <summary>
        /// 多文件上傳
        /// </summary>
        /// <param name="_hostingEnvironment"></param>
        /// <returns></returns>
        public async Task<IActionResult> ManySaveFile([FromServices] IWebHostEnvironment _hostingEnvironment)
        {
            try
            {
                long size = 0;   //統計上傳文件的大小(單位b)
                var files = Request.Form.Files;  //獲取文件
                if (files.Count == 0)
                {
                    return Json(new { status = "error", msg = "上傳內容為空", data = "" });
                }
                List<string> rUrlList = new List<string>();
                //多文件遍歷上傳
                foreach (var file in files)
                {
                    //獲取文件擴展名
                    var fileName = file.FileName;
                    int idxStart = fileName.LastIndexOf(".");
                    string areviation = fileName.Substring(idxStart, fileName.Length - idxStart);

                    //編輯文件的存儲路徑
                    var filePath = _hostingEnvironment.ContentRootPath + @"\DownLoad\Picture\";
                    if (!Directory.Exists(filePath))
                    {
                        Directory.CreateDirectory(filePath);
                    }
                    //編輯文件的名稱(目前是隨機命名,如果用原名保存,需要判重)
                    var myFileName = $"{Guid.NewGuid().ToString()}{areviation}";
                    //最終路徑
                    var finalPath = filePath + myFileName;
                    size += file.Length;
                    using (FileStream fs = System.IO.File.Create(finalPath))
                    {
                        await file.CopyToAsync(fs);
                        await fs.FlushAsync();
                    }

                    //DB中存儲的或者返回給前端的都是相對路徑
                    string relativeUrl = $"/DownLoad/Picture/{myFileName}";
                    rUrlList.Add(relativeUrl);

                }
                return Json(new { status = "ok", msg = "上傳成功", data = rUrlList });
            }
            catch (Exception ex)
            {
                return Json(new { status = "error", msg = "上傳失敗", data = "" });
            };
        } 
        #endregion
View Code

 

二. 基於LayUI文件上傳

1.相關地址

 官方文檔:https://www.layui.com/doc/modules/upload.html

 官方樣例:https://www.layui.com/demo/upload.html

2. 各種樣例

(1). 單文件上傳

 A.基礎配置:Header表頭、data參數、acceptMime篩選文件類型、accept+exts允許上傳的文件和后綴、Size最大上傳大小等

 B.幾個回調:choose選擇文件后回調、before文件提交前回調、done上傳成功后回調、error請求異常回調

代碼分享:

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>文件上傳</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <link href="~/src/layuiadmin/layui/css/layui.css" rel="stylesheet" />
    <link href="~/src/layuiadmin/style/admin.css" rel="stylesheet" />
    <style>
        .c1 {
            width: 500px;
            height: 280px;
            border: 1px solid black;
            padding: 20px;
            float: left;
        }

        img {
            width: 200px;
            height: 200px;
        }
    </style>
</head>
<body>
    <div class="c1">
        <button type="button" class="layui-btn" id="test1">
            單文件上傳(各種屬性)
        </button>
        <br />
        <div>
            <img src="/DownLoad/Picture/demo.png" id="j_img1" />
        </div>

    </div>

    

    <script src="~/src/layuiadmin/layui/layui.js"></script>
    <script>
        layui.use(['upload', 'jquery'], function () {
            var $ = layui.$;
            var upload = layui.upload;

            //1.單文件上傳
            var uploadInst1 = upload.render({
                elem: '#test1',               //綁定元素
                url: 'SingleSaveFile',        //上傳接口
                headers: { auth: window.localStorage.getItem("token") },  //表頭
                data: {},                     //額外參數
                acceptMime: 'image/*',        //選擇框篩選文件類型(不是很准確)
                accept: "file",               //允許上傳所有文件
                //exts:"zip|rar|7z",                    //允許上傳的后綴的類型,和accept配合使用
                size: 0,                      //設置文件最大可允許上傳的大小,單位 KB, 0表示不限制
                choose: function (obj) {
                    //選擇文件后回調
                },
                before: function () {
                    //文件提交前回調
                    layer.load(); //上傳loading
                },
                done: function (res) {
                    //上傳成功后回調
                    if (res.status == "ok") {
                        alert(res.msg);
                        $("#j_img1").attr("src", res.data);

                        layer.closeAll('loading'); //關閉loading
                    }
                },
                error: function (index, upload) {
                    //請求異常回調

                    layer.closeAll('loading'); //關閉loading
                }
            });

          

        });
    </script>


</body>
</html>
View Code

運行效果:

(2).多文件上傳

A. 原理

 LayUI的多文件上傳只是一次可以選多個文件而已,是通過調用多次接口實現的,目前沒有實現調用一次接口,所以這里還是調用SingleSaveFile,對於前端而言done回調每成功1個文件回調1次, allDone當所有文件提交后才能被觸發,會返回文件總數、成功文件數、失敗文件數。

B. 核心配置

 (1). multiple: true,  //允許多文件上傳

 (2). number: 2,  //允許上傳的文件數量,配合multiple使用

代碼分享:

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>文件上傳</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <link href="~/src/layuiadmin/layui/css/layui.css" rel="stylesheet" />
    <link href="~/src/layuiadmin/style/admin.css" rel="stylesheet" />
    <style>
        .c1 {
            width: 500px;
            height: 280px;
            border: 1px solid black;
            padding: 20px;
            float: left;
        }

        img {
            width: 200px;
            height: 200px;
        }
    </style>
</head>
<body>

    <div class="c1">
        <button type="button" class="layui-btn" id="test2">
            多文件上傳
        </button>
        <br />
        <div id="j2">
        </div>
    </div>

  

    <script src="~/src/layuiadmin/layui/layui.js"></script>
    <script>
        layui.use(['upload', 'jquery'], function () {
            var $ = layui.$;
            var upload = layui.upload;
         
            //2.多文件上傳
            var uploadInst2 = upload.render({
                elem: '#test2',               //綁定元素
                url: 'SingleSaveFile',        //上傳接口
                headers: { auth: window.localStorage.getItem("token") },  //表頭
                data: {},                     //額外參數
                acceptMime: 'image/*',        //選擇框篩選文件類型(不是很准確)
                accept: "file",               //允許上傳所有文件
                //exts:"zip|rar|7z",          //允許上傳的后綴的類型,和accept配合使用
                size: 0,                      //設置文件最大可允許上傳的大小,單位 KB, 0表示不限制
                multiple: true,               //允許多文件上傳
                number: 2,                    //允許上傳的文件數量,配合multiple使用
                choose: function (obj) {
                    //選擇文件后回調
                },
                before: function () {
                    //文件提交前回調
                    layer.load(); //上傳loading
                },
                allDone: function (obj) {
                    //當文件全部被提交后,才觸發
                    console.log(obj.total); //得到總文件數
                    console.log(obj.successful); //請求成功的文件數
                    console.log(obj.aborted); //請求失敗的文件數

                    layer.closeAll('loading'); //關閉loading
                },
                done: function (res) {
                    //上傳成功后回調(每成功一個文件,回調一次)
                    if (res.status == "ok") {
                        $("#j2").append('<img src="' + res.data + '"/>');
                    }
                },
                error: function (index, upload) {
                    //請求異常回調
                    //當上傳失敗時,你可以生成一個“重新上傳”的按鈕,點擊該按鈕時,執行 upload() 方法即可實現重新上傳

                    layer.closeAll('loading'); //關閉loading
                }
            });

        
        });
    </script>


</body>
</html>
View Code

運行效果:

(3).非自動上傳+隊列

大致流程:

 通過 auto: false設置不自動上傳,然后通過 bindAction: '#test33' 指向一個按鈕綁定上傳,選擇文件后進入choose回調,將文件存放到本地隊列中,並且可以操作DOM,用於提前預覽,上傳成功后,修改本地DOM或者刪除; 上傳失敗后,將本地DOM改為重新上傳。

代碼分享:

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>文件上傳</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <link href="~/src/layuiadmin/layui/css/layui.css" rel="stylesheet" />
    <link href="~/src/layuiadmin/style/admin.css" rel="stylesheet" />
    <style>
        .c1 {
            width: 500px;
            height: 280px;
            border: 1px solid black;
            padding: 20px;
            float: left;
        }

        img {
            width: 200px;
            height: 200px;
        }
    </style>
</head>
<body>

    <div class="c1">
        <button type="button" class="layui-btn" id="test3">
            非自動上傳+隊列
        </button>
        <button type="button" class="layui-btn" id="test33">
            點我上傳
        </button>
        <br />
        <div id="j3">
        </div>
    </div>

    <script src="~/src/layuiadmin/layui/layui.js"></script>
    <script>
        layui.use(['upload', 'jquery'], function () {
            var $ = layui.$;
            var upload = layui.upload;

            //3.非自動上傳+隊列
            var uploadInst3 = upload.render({
                elem: '#test3',               //綁定元素
                url: 'SingleSaveFile',        //上傳接口
                headers: { auth: window.localStorage.getItem("token") },  //表頭
                data: {},                     //額外參數
                acceptMime: 'image/*',        //選擇框篩選文件類型(不是很准確)
                accept: "file",               //允許上傳所有文件
                //exts:"zip|rar|7z",          //允許上傳的后綴的類型,和accept配合使用
                size: 0,                      //設置文件最大可允許上傳的大小,單位 KB, 0表示不限制
                multiple: true,               //允許多文件上傳
                number: 2,                    //允許上傳的文件數量,配合multiple使用
                auto: false,                   //選擇文件后不自動上傳
                bindAction: '#test33', //指向一個按鈕觸發上傳
                choose: function (obj) {
                    //選擇文件后回調
                    //將每次選擇的文件追加到文件隊列
                    var files = obj.pushFile();
                    //預讀本地文件,如果是多文件,則會遍歷。(不支持ie8/9)
                    obj.preview(function (index, file, result) {
                        console.log(index); //得到文件索引
                        console.log(file); //得到文件對象
                        //console.log(result); //得到文件base64編碼,比如圖片
                        //obj.resetFile(index, file, '123.jpg'); //重命名文件名,layui 2.3.0 開始新增

                        //這里還可以做一些 append 文件列表 DOM 的操作
                        var tr = $(['<tr id="upload-' + index + '">'
                            , '<td>' + file.name + '</td>'
                            , '<td>' + (file.size / 1024).toFixed(1) + 'kb</td>'
                            , '<td>等待上傳</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();
                            uploadInst3.config.elem.next()[0].value = ''; //清空 input file 值,以免刪除后出現同名文件不可選
                        });

                        $("#j3").append(tr);


                        //obj.upload(index, file); //對上傳失敗的單個文件重新上傳,一般在某個事件中使用
                        //delete files[index]; //刪除列表中對應的文件,一般在某個事件中使用
                    });


                },
                before: function () {
                    //文件提交前回調
                    //layer.load(); //上傳loading
                },
                allDone: function (obj) {
                    //當文件全部被提交后,才觸發

                },
                done: function (res) {
                    //上傳成功后回調(每成功一個文件,回調一次)
                    if (res.status == "ok") {
                        $("#j3").append('<img src="' + res.data + '"/>');

                        //刪除列表中待上傳的文件(或者改里面的內容,改成上傳成功)
                    }
                },
                error: function (index, upload) {
                    //請求異常回調
                   //配置上面顯示重傳按鈕

                }
            });

        });
    </script>


</body>
</html>
View Code

運行效果: 

 

三. 基於dropzonejs文件上傳

1. 相關地址

 官網:https://www.dropzonejs.com/ (含文檔和下載地址)

2. 各種樣例

(1).單文件上傳

 maxFiles: 1 將該屬性設置為1,只能選擇一個文件上傳。

 另外:該控件默認會生成一個縮略圖框,我們很多情況下不需要,可以采用下面的方式來解決。

 previewsContainer: '#hid', //將縮略圖存放到指定位置(然后將該位置隱藏,則不顯示縮略圖了)

(2).多文件上傳

A.原理:這里的多文件上傳只調用一次接口!!

B.核心配置:

 uploadMultiple: true, //開啟單次請求上傳多個文件, 配合下面的parallelUploads適用

 parallelUploads: 6, //並行允許上傳文件的個數

 maxFiles: 6, //一次性上傳的文件數量上限

 successmultiple和errormultiple //多文件成功回調 和 失敗回調 (只調一次)

代碼分享:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>樣例1</title>
        <style>
            .c1 {
                    width: 600px;
                    height: 280px;
                    border: 1px solid black;
                    padding: 20px;
                    float: left;
                }
        
             img {
                    width: 150px;
                    height: 150px;
                }
            </style>
        <script src="../../../js/easyui/jquery.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="../../../js/utils/dropzone.js" type="text/javascript" charset="utf-8"></script>

        <script type="text/javascript">
            $(function() {
                // 單文件上傳
                $("#test1").dropzone({
                    url: "http://localhost:29793/Demo_Areas/Demo1/SingleSaveFile",
                    method: 'post',
                    createImageThumbnails: false, //前端不生成縮略圖(只是不生成圖,但縮略框還在)
                    headers: {
                        "auth": window.localStorage.getItem("token")
                    },
                    timeout: 1000000, //超時時間,單位毫秒, 默認30s
                    maxFiles: 1, //一次性上傳的文件數量上限(選擇的時候最多選1個文件,無法多選)        
                    maxFilesize: 10, //最大文件上傳大小 單位: MB
                    previewsContainer: '#hid', //將縮略圖存放到指定位置(將該位置隱藏,則不顯示縮略圖了)                
                    acceptedFiles: "image/*,application/pdf,.psd,.txt", //上傳的類型    
                    dictMaxFilesExceeded: "您最多只能一次上傳n個文件", //替換文件數量超限的限制
                    dictInvalidFileType: '不支持該文件類型上傳', //替換不支持類型上傳的文案
                    dictFileTooBig: '您上傳的文件太大,最大允許10M', //替換文件太大的文案
                    dictFallbackMessage: '您的瀏覽器不支持該上傳控件', //替換瀏覽器不支持的文案
                    init:function(){        
                        var that=this;
                        this.on("complete",function(file){
                            // that.removeFile(file);
                            that.removeAllFiles();     //執行完畢后,刪除本地記錄,使其可以繼續上傳(類似重置控件)
                        });
                    },
                    sending: function(x1, x2, x3) {
                        //發送文件之前調用,參數詳見文檔
                    },
                    success: function(file, res, e) {
                        if (res.status == "ok") {
                            var myUrl = "http://localhost:29793" + res.data;
                            $("#j1").append('<img src="' + myUrl + '"/>');
                        }
                    },
                    error: function(x1, errorMsg, xhr) {
                        if (x1.status == "error") {
                            alert(errorMsg);
                        }
                    }
                });
                //多文件上傳
                $("#test2").dropzone({
                    url: "http://localhost:29793/Demo_Areas/Demo1/ManySaveFile",
                    method: 'post',
                    createImageThumbnails: false, //前端不生成縮略圖(只是不生成圖,但縮略框還在)
                    headers: {
                        "auth": window.localStorage.getItem("token")
                    },
                    timeout: 1000000, //超時時間,單位毫秒, 默認30s
                    uploadMultiple: true, //開啟單次請求上傳多個文件, 配合下面的parallelUploads適用
                    parallelUploads: 6, //並行允許上傳文件的個數
                    maxFiles: 3, //一次性上傳的文件數量上限        
                    maxFilesize: 10, //最大文件上傳大小 單位: MB
                    previewsContainer: '#hid', //將縮略圖存放到指定位置(將該位置隱藏,則不顯示縮略圖了)                
                    acceptedFiles: "image/*,application/pdf,.psd,.txt", //上傳的類型        
                    dictMaxFilesExceeded: "您最多只能一次上傳n個文件", //替換文件數量超限的限制
                    dictInvalidFileType: '不支持該文件類型上傳', //替換不支持類型上傳的文案
                    dictFileTooBig: '您上傳的文件太大,最大允許10M', //替換文件太大的文案
                    dictFallbackMessage: '您的瀏覽器不支持該上傳控件', //替換瀏覽器不支持的文案
                    init:function(){
                        var that=this;
                        this.on("complete",function(file){
                            that.removeAllFiles();    //執行完畢后,刪除本地記錄,使其可以繼續上傳(類似重置控件)
                        });
                    },
                    sendingmultiple: function(x1, x2, x3) {
                        //發送文件之前調用,參數詳見文檔
                    },
                    //多文件成功回調, 不能適用success回調,success會觸發多次
                    successmultiple: function(file, res, e) {
                        console.log(res);
                        if (res.status == "ok") {
                            for (var i = 0; i < res.data.length; i++) {
                                var myUrl = "http://localhost:29793" + res.data[i];
                                $("#j2").append('<img src="' + myUrl + '"/>');
                            }
                        }
                    },
                    errormultiple: function(x1, errorMsg, xhr) {
                        if (x1.status == "error") {
                            alert(errorMsg);
                        }
                    },
                    error: function(x1, errorMsg, xhr) {
                        if (x1.status == "error") {
                            alert(errorMsg);
                        }
                    }
                });



            });
        </script>
    </head>
    <body>
        <p>圖片上傳dropzone樣例</p>
        <div class="c1">
            <button type="button" class="layui-btn" id="test1">
                單文件上傳(各種屬性)
            </button>
            <br />
            <div id="j1">
            </div>
        </div>

        <div class="c1">
            <button type="button" class="layui-btn" id="test2">
                多文件上傳
            </button>
            <br />
            <div id="j2">
            </div>
        </div>


        <div id="hid" style="display: none;">
            用來存放縮略圖,但不顯示,目前沒有找到直接關閉縮略圖的屬性
        </div>
    </body>
</html>
View Code

 運行截圖:

3. 其它

 支持隊列上傳、文件分塊上傳、拖拽、其它各種情況的回調等等。

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鵬飛)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 聲     明1 : 如有錯誤,歡迎討論,請勿謾罵^_^。
  • 聲     明2 : 原創博客請在轉載時保留原文鏈接或在文章開頭加上本人博客地址,否則保留追究法律責任的權利。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM