zoukankan      html  css  js  c++  java
  • MVC之文件上传1

    MVC之文件上传

    前言

    这一节我们来讲讲在MVC中如何进行文件的上传,我们逐步深入,一起来看看。

    Upload File(一)

    我们在默认创建的项目中的Home控制器下添加如下:

    复制代码
            public ActionResult UploadFile()
            {
                return View();
            }
    
            [HttpPost]
            public ActionResult UploadFile(HttpPostedFileBase file)
            {
                var fileName = file.FileName;
                var filePath = Server.MapPath(string.Format("~/{0}", "File"));
                file.SaveAs(Path.Combine(filePath, fileName));
                return View();
            }
    复制代码

    在 UploadFile 视图中添加上如下:

    <form action="/Home/UploadFile" method="post" enctype="multipart/form-data">
        <input type="file" name="file" /><br />
        <input type="submit" value="提交" />
    </form>

    有关视图中我们就不必多说,只需明白如下两点:

    (1)在后台利用HttpPostedFileBase来接收上传文件,该类为一个抽象类,但在ASP.NET Web Form却没有此类,此类的出现是为了更好的进行单元测试。

    (2)在视图中文件类型的name要和后台接收文件的参数一致。

    接下来我们进行演示看看结果:

     上述我们简单的上传了一个Excel文件,下面我们通过强类型视图以及模型验证来强化上传。

    Upload File(二)

    我们创建如下BlogModel类:

    复制代码
        public class BlogModel
        {
            [Display(Name = "博客名称")]
            [Required(ErrorMessage = "请输入你的博客名称!")]
            public string BlogName { get; set; }
    
            [Display(Name = "博客地址")]
            [Required(ErrorMessage = "请输入你的博客地址!")]
            public string BlogAddress { get; set; }
    
            [Display(Name = "博客图片")]
            [Required(ErrorMessage = "请上传你的博客图片!")]
            [ValidateFile]
            public HttpPostedFileBase BlogPhoto { get; set; }
        }
    复制代码

    上述未有验证文件的特性,只能自定义文件特性,如下:

    复制代码
        public class ValidateFileAttribute : ValidationAttribute
        {
            public override bool IsValid(object value)
            {
                int MaxContentLength = 1024 * 1024 * 4;
                string[] AllowedFileExtensions = new string[] { ".jpg", ".gif", ".png", ".pdf" };
    
                var file = value as HttpPostedFileBase;
    
                if (file == null)
                    return false;
                else if (!AllowedFileExtensions.Contains(file.FileName.Substring(file.FileName.LastIndexOf('.'))))
                {
                    ErrorMessage = "请上传你的博客图片类型: " + string.Join(", ", AllowedFileExtensions);
                    return false;
                }
                else if (file.ContentLength > MaxContentLength)
                {
                    ErrorMessage = "上传图片过大,不能超过4兆 : " + (MaxContentLength / 1024).ToString() + "MB";
                    return false;
                }
                else
                    return true;
            }
        }
    复制代码

    我们可以任意设置上传的文件大小,我们设置为40兆,在配置文件中我们知道 maxRequestLength = 4096 默认是4兆,当然我们可以改变其默认设置。

        <httpRuntime targetFramework="4.5" executionTimeout="1100"  maxRequestLength="40960" />

    此时我们接着在控制器中修改上述上传的方法:

    复制代码
            [HttpPost]
            public ActionResult UploadFile(BlogModel bModel)
            {
                if (ModelState.IsValid)
                {
                    var fileName = bModel.BlogPhoto.FileName;
                    var filePath = Server.MapPath(string.Format("~/{0}", "File"));
                    bModel.BlogPhoto.SaveAs(Path.Combine(filePath, fileName));
                    ModelState.Clear();
                }          
                return View();
            }
    复制代码

    我们接下来看看效果:

    咋回事,出状况了看来是我们的文件过大的原因,看了下该文件有接近45兆,而我们却设置的是40兆,于是乎继续在配置文件中去修改文件大小,但是结果还是一样。我们继续仔细看看该结果的提示,根据提示去找到配置文件下的节点再试试,我们在 syste.webServer 节点下设置为2G:

    复制代码
        <security>
          <requestFiltering>
            <requestLimits maxAllowedContentLength="2147483647">
            </requestLimits>
          </requestFiltering>
        </security>
    复制代码

    结果就好使了,查了查也有遇到类似问题的人,貌似只有给个结果,却没有给解释,为什么在 httpRuntime 中设置不行,但是有些这样设置是正确的,这是什么原因?最终找到了答案:

    (1)在IIS 5和IIS 6中,默认文件上传的最大为4兆,当上传的文件大小超过4兆时,则会得到错误信息,但是我们通过如下来设置文件大小。

    <system.web>
      <httpRuntime maxRequestLength="2147483647" executionTimeout="100000" />
    </system.web>

    (2)在IIS 7中,默认文件上传的最大为28.6兆,当超过其默认设置大小,同样会得到错误信息,但是我们却可以通过如下来设置文件上传大小。

    复制代码
    <system.webServer>
      <security>
        <requestFiltering>
          <requestLimits maxAllowedContentLength="2147483647" />
        </requestFiltering>
      </security>
    </system.webServer>
    复制代码

    【类推的话,个人觉得可能是在IIS 7+以上都是通过如上述IIS 7来设置文件上传大小】

    虽然我们在服务器端对其进行验证,但是我们觉得这样还是不能保险,我们继续在客户端对其上传的图片类型和大小进行验证。 

    (1)利用强类型视图给出视图代码:

    复制代码
    <style type="text/css">
        .field-validation-error {
            color: red;
        }
    </style>
    <form id="uploadFileSub" action="/Home/UploadFile" method="post" enctype="multipart/form-data">
        <fieldset>
            <legend></legend>
            <ul class="lifile">
                <li>
                    @Html.LabelFor(m => m.BlogName)<br />
                    @Html.TextBoxFor(m => m.BlogName, new { maxlength = 50 })
                    @Html.ValidationMessageFor(m => m.BlogName)
                </li>
                <li>
                    @Html.LabelFor(m => m.BlogAddress)<br />
                    @Html.TextBoxFor(m => m.BlogAddress, new { maxlength = 200 })
                    @Html.ValidationMessageFor(m => m.BlogAddress)<br />
                </li>
                <li>
                    @Html.LabelFor(m => m.BlogPhoto)
                    @Html.TextBoxFor(m => m.BlogPhoto, new { type = "file" })
                    @Html.ValidationMessageFor(m => m.BlogPhoto)
                    <span id="warning" style="color:red;font-size:large;"></span>
                </li>
                <li>
                    <input type="submit" value="提交" />
                </li>
            </ul>
    
        </fieldset>
    </form>
    复制代码

    (2)利用脚本获取上传文件大小:

    复制代码
        function GetFileSize(fileid) {
            var fileSize = 0;
            fileSize = $("#" + fileid)[0].files[0].size;
            fileSize = fileSize / 1048576;
            return fileSize;
        }
    复制代码

    (3)根据上传的路径获取文件名称:

    复制代码
        function getNameFromPath(strFilepath) {
            var objRE = new RegExp(/([^/\]+)$/);
            var strName = objRE.exec(strFilepath);
    
            if (strName == null) {
                return null;
            }
            else {
                return strName[0];
            }
        }
    复制代码

    (4)当更换文件时触发Change事件对其文件类型和文件大小进行验证:

    复制代码
            $("#BlogPhoto").change(function () {
                var file = getNameFromPath($(this).val());
                if (file != null) {
                    var errors = $(document).find(".field-validation-error");
                    $.each(errors, function (k, v) {
                        if ($(v).attr("data-valmsg-for") === "BlogPhoto") {
                            $(v).hide();
                        }
                    });
                    var extension = file.substr((file.lastIndexOf('.') + 1));
                    switch (extension) {
                        case 'jpg':
                        case 'png':
                        case 'gif':
                        case 'pdf':
                            fileTypeBool = false;
                            break;
                        default:
                            fileTypeBool = true;
                    }
                }
                if (fileTypeBool) {
                    $("#warning").html("只能上传扩展名为jpg,png,gif,pdf的文件!");
                    return false;
                }
                else {
                    var size = GetFileSize('BlogPhoto');
                    if (size > 4) {
                        fileSizeBool = true;
                        $("#warning").html("上传文件已经超过4兆!");
                    } else {
                        fileSizeBool = false;
                    }
                }
            });
    复制代码

    (5)当点击提交按钮时对其进行文件进行验证:

    复制代码
            $("#uploadFileSub").submit(function () {
                $("input[type='text']").each(function (k, v) {
                    if ($(v).length) {
                        $(v).siblings("span").hide();
                    }
                });
                if (fileTypeBool || fileSizeBool) {
                    return false;
                }
            });
    复制代码

    【注意】上述对于验证不是太完整,但是基本的架子已经给出。

    接下来我们来完整的演示整个过程。 

     

    上述我们一直是利用的纯HTML代码,当然也可以利用MVC的扩展方法来进行,如下(最终渲染的还是表单,本质上是一致的,就不做过多探讨了)

    复制代码
    @using (Html.BeginForm("UploadFile", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
    { 
    
     <input type="file" id="file" name="file" />
     <input type="submit" value="提交" />
    }
    复制代码

    结语

    这一节我们比较详细的讲述了在MVC中如何进行文件的上传,但是我们还有一点未曾讲到,则是利用流来将如我们上述的图片转换成字节来插入到数据库中。有关上传可以参考园友Insus.NET对此利用流来上传。

  • 相关阅读:
    CF704D Captain America 上下界网络流
    CF241E Flights 差分约束
    CF1063F String Journey DP、SAM、线段树
    AGC028E High Elements 贪心、DP、线段树
    Solution -「CF 623E」Transforming Sequence
    Solution -「十二省联考2019」春节十二响
    最大团-最小度不等式
    「Lagrange 插值」学习笔记
    Solution -「NOI.AC 省选膜你赛」union
    Solution -「NOI.AC 省选膜你赛」T2
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/5437547.html
Copyright © 2011-2022 走看看