zoukankan      html  css  js  c++  java
  • 第六节:基于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 + @"DownLoadPicture";
                    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 + @"DownLoadPicture";
                        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 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    一文带你了解接口测试价值与体系
    干货|app自动化测试之设备交互API详解
    干货|app自动化测试之Appium问题分析及定位
    干货| app自动化测试之Andriod微信小程序的自动化测试
    如果你也有这些职场困惑,周六一直线上答疑
    文末福利 | 团队管理第一步之高效招聘
    精准化测试原理简介与实践探索
    文末有福利 | 面试时如何命中面试官的考题?
    Visual studio prebuild/postbuild 设置条件不生效
    使用腾讯地图api获取定位信息经纬度(需要浏览器支持,且需要https)
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/14307822.html
Copyright © 2011-2022 走看看