zoukankan      html  css  js  c++  java
  • ASP.NET MVC 4 批量上传文件

    上传文件的经典写法:

    <form id="uploadform" action="/Home/UploadFile" method="post" enctype="multipart/form-data">
        <input type="file" name="uploadfile" />
        <input type="submit" value="上传" />
    </form>

    这里的表单form里只有1个file,所以也就只能一次上传一个文件。如果需要上传的文件很多,希望在打开浏览文件窗口后可以用鼠标框选或按着键盘的ctrl键用鼠标去点选,该怎么办呢?

    第一种方法——有几个file就在form里写几个file:

    <input type="file" name="uploadfile" />
    <input type="file" name="uploadfile" />
    <input type="file" name="uploadfile" />
    <input type="file" name="uploadfile" />
    <input type="file" name="uploadfile" />
    ......

    Oh my god !

    如果有20个文件要上传的话就写20个<input type="file" name="uploadfile" />?不可以!

    第二种方法——用jquery克隆文件

    这样form里还是只写一个file,然后用jquey去动态添加。效果如图:

    <form id="uploadform" action="/Home/UploadFile" method="post" enctype="multipart/form-data">
    当前有<span id="inputNum">1</span>个文本框,已选择<label id="fileNum">0</label>个文件。
      <div id="upload">
          <input type="file" name="uploadfile" style="border: 1px solid gray;  500px;" />
      </div>
      <input type="submit" value="上传" />
    </form>
    <div id="status"></div>

    我们想在文本框后面加一个“添加”、“删除“的链接,点击后增加一个文件框或删除。

    既然这个input file是动态添加的,那么后面跟着的“取消”、”增加”也是跟着一起创建的。本以为很难,结果用jquery反而很简单的:

    $("input[type=file]").after(
                //" <a href='#' class='clear-inputfile'>清除内容</a>" + " | " +
                " <a href='#' class='removeInputFile'>取消</a>    " + " | " +
                " <a href='#' class='addInputFile'>增加</a>"
     );

    先用input[type=file]找到这个inputy,然后在他的后面(after)加上超链接(a),就这么简单!

    Jquery:

    //增加多个文本框 (复制当前行)         
            $('.addInputFile').click(function () {
                var clone = $(this).parent().clone(true);//true:连事件一起复制
                var file = clone.children("input[type=file]").val(null);
                $(clone).insertAfter($(this).parent());
            });

    clone() 方法

    定义和用法

    clone() 方法生成被选元素的副本,包含子节点、文本和属性。

    语法

    $(selector).clone(includeEvents)

    这里把事件一起复制了,所以是:

    var clone = $(this).parent().clone(true);

    注意我们复制的是<div id="upload">。

    如果已经选择了文件,克隆后会把文件框里的内容一起复制过来,所以在val()中加上null清除内容:

    var file = clone.children("input[type=file]").val(null);

    增加后也要有取消,当取消到只剩一个的时候给个提示。

    //删除            
            $('.removeInputFile').click(function () {
                var num = $('#upload input[type=file]').length;
                if (num == 1) {
                    alert('必须保留一个!');
                    return false;
                }
                $(this.parentElement).remove();
            });

    动态添加文件操作完毕!

    上传文件后如果刷新浏览器会再次提交,这个问题很普遍,一不注意就重复提交了。所以这里采用ajax的方式上传文件!用mvc的Ajax.BeginForm吗?这个就是异步的啊!但是如果不配合一个插件来的话,单靠Ajax.BeginForm还是不能完成异步上传文件并且避免刷新重复提交!!这个插件就是jquery.form.js

    $('form').ajaxForm({
                dataType: "html",//json也可以,以避免FF里此错误:HierarchyRequestError: Node cannot be inserted at the specified point in the hierarchy
                ///判断是否有文件 formData不支持IE!
                ///formData is an array of objects 
                ///representing the name and value of each field that will be sent to the server;
                beforeSubmit: function (formData) {
                    //没有选择文件则退出
                    if (selectedFileNum() == 0) {
                        alert("请选择文件!");
                        return false;
                    }
                },
                success: function (responseText) {//responseText:后台传来的string                            
                    status.html(responseText);
                },
                error: function (xhr, textStatus, errorThrown) {//在前端挡住请求
                    alert('文档上传错误.' + xhr.responseText);//例如文件过大等错误
                    status.html(xhr.responseText);
                },
                complete: function (xhr) {
                    status.html(xhr.responseText);
                    $("form").resetForm();//重置表单
                }
            });//end jquey.form

    Ajax.BeginForm也要配合jquery.form.plugin一起使用

    Ajax.BeginForm的写法:

    @using (Ajax.BeginForm(
                            "UploadFile", 
                            "Home",
                            new AjaxOptions
                            {
                                UpdateTargetId = "status",
                                HttpMethod = "Post"
                            }, 
                            new { enctype = "multipart/form-data" }
                            )
            )
    {
        <div id="upload">
            <input type="file" name="uploadfile" style="border: 1px solid gray;" />
        </div>
        <input type="submit" value="上传" />
    }

    目前都是前端的操作,接下来看后台的保存文件到服务器是怎么做的。

    Controller:

    //上传文件
            [HttpGet]
            public ActionResult UploadFile() { return View(); }
            [HttpPost]
            public ActionResult UploadFile(IEnumerable<HttpPostedFileBase> uploadfile)
            {
                foreach (var file in uploadfile)
                {
                    if (file != null && file.ContentLength > 0)
                    {
                        var fileName = Path.GetFileName(file.FileName);
                        var path = Path.Combine(Server.MapPath("~/Uploads"), fileName);
                        //如遇相同文件则先删除再保存
                        if (System.IO.File.Exists(path))
                            System.IO.File.Delete(path);
                        file.SaveAs(path);
                    }
                }
               return Content("上传完毕!");
            } 

    因为上传的是多个文件,所以这里要用IEnumerable<HttpPostedFileBase>类型。使用HttpPostedFileBase来接收传递的文件是ASP.NET MVC的推荐做法,不推荐用Request。要注意HttpPostedFileBase类型的参数uploadfile这个名称要和前端form里的input的name保持一致!

    第三种方法——使用jquery上传插件

    上面说那么多,其实这个才是主角。

    要想一次性在浏览窗口中选中多个文件同时上传到服务器,还是要用个插件才方便。寻觅很久还是发现uploadify最合心意,其他的也很优秀,但是在IE浏览器里无法一次多选,只能是点一次选一个点一次选一个,然后一起上传。

    uploadify常用的一些设置:

    $(document).ready(function () {
            $("#myUploadFile").uploadify({
                //属性
                'auto': true, //自动上传
                'height': 30, //按钮的高度
                'width': 80, //按钮的宽度
                'swf': '../Scripts/Uploadify/uploadify.swf', //必输入!flash.注意路径!!
                'fileObjName': 'uploadfile', //传递给后台程序的参数, 否则会接收不到!
                'uploader': '../Home/Uploadify', //后台处理程序. 注意路径!!
                'queueID': 'queue', //显示上传队列的容器
                'buttonText': '选择文件', //按钮显示文字
                //'fileSizeLimit': '5MB',
                //'queueSizeLimit': 5, //同时允许上传5个文件
                'fileTypeExts': '*.xls;*.xlsx',
                'removeCompleted': false, //上传后保持队列不消失
                'requeueErrors': true,
                //事件
                'onSelect': function (file)//从浏览窗口中选择文件
                {
                    if (file.size / 1024 / 1024 > 10) //文件10M
                    {
                        alert('文件过大,请分批上传!');
                        $('#myUploadFile').uploadify('cancel', file.id); //cancel方法可以带上file的id作为参数,指定取消该项。
                    }
                },
                'onCancel': function (file)//从队列中取消文件 
                {
                    //alert('文件: ' + file.name + ' 被取消.');
                    //document.getElementById("fileCount").value -= 1;
                },
                'onClearQueue': function (queueItemCount) {//只在未上传前有效,上传后其实还保存在队列中。
                    //alert(queueItemCount + ' file(s) were removed from the queue');
                },
                'onDialogClose': function (queueData) //当浏览窗口关闭时
                {
                    //alert(queueData.filesQueued + ' files were queued of ' + queueData.filesSelected + ' selected files. There are ' + queueData.queueLength + ' total files in the queue.');
                    //document.getElementById("fileCount").value = queueData.queueLength; //队列中文件数量
                    //document.getElementById("lblStatus").innerText = "";
                },
                'onQueueComplete': function (queueData)//全部上传完毕后触发
                {
                    //alert(queueData.uploadsSuccessful + ' 个文件成功上传。上传后请点击“提交”。');
                    //document.getElementById("fileCount").value = "";
                    //window.location.href = "Default.aspx"//重加载页面
                    // window.location.reload(); //
                    //alert("reload");
                    //alert("upload Done");
                },
                'onUploadError': function (file, errorCode, errorMsg, errorString) {
                    alert('The file ' + file.name + ' 上传失败: ' + errorString);
                    //alert('errorCode:'+errorCode);
                    //alert('errormsg:' + errorMsg);//500
                    //alert('errorString:' + errorString);//HTTP Error (500)
                },
                'onUploadSuccess': function (file, data, response) {
                    //alert('The file ' + file.name + ' 上传成功!');
                    //alert('data is :' + data);//data是controller传来的str
                    $('#msg').text(data);
                    //alert('response is :' + response); //response is true
                },
                'onSelectError': function (file, errorCode, errorMsg) //错误信息
                {
                    switch (errorCode) {
                        case -100:
                            alert("上传的文件数量已超过系统限制的" + $('#myUploadFile').uploadify('settings', 'queueSizeLimit') + "个文件");
                            break;
                        case -110:
                            alert("文件(" + file.name + ")大小超出系统限制的" + $('#myUploadFile').uploadify('settings', 'fileSizeLimit') + "大小!");
                            break;
                        case -120:
                            alert("文件(" + file.name + ")大小异常!");
                            break;
                        case -130:
                            alert("文件(" + file.name + ")类型不正确!");
                            break;
                    }
                }
            });
        });
    
    <input type="file" id="myUploadFile" />
    <p id="queue"></p>

    Controller:

         [HttpGet]
            public ActionResult Uploadify() { return View(); }
            [HttpPost]
          public ActionResult Uploadify(HttpPostedFileBase uploadfile)
            {
                if (uploadfile != null && uploadfile.ContentLength > 0)
                {
                    var fileName = Path.GetFileName(uploadfile.FileName);
                    var path = Path.Combine(Server.MapPath("~/Uploads"), fileName);
                    if (System.IO.File.Exists(path))
                        System.IO.File.Delete(path);
                    uploadfile.SaveAs(path);
                }
                return Content("上传完毕!");
            }

    这样就满足了同时上传文件的需要——在IE里。

    --End--

  • 相关阅读:
    ObjectiveC语法快速参考
    IIS网站全部显示无权访问需要登录
    如何让自己的网站尽快收录绍兴114导航
    asp.net的运行原理
    WPF学习视频资料
    Asp.net MVC3 自定义HtmlHelper控件
    Unity3D中C#和JS的方法互相調用
    对于冒泡算法的思考,大牛可一笑而过~~
    2013年年前瞻望与计划
    使用vs2010编辑Unity脚本,配置方法
  • 原文地址:https://www.cnblogs.com/ibgo/p/3515224.html
Copyright © 2011-2022 走看看