ASP.NET MVC之文件上传【二】(九)

前言

上一节我们讲了简单的上传以及需要注意的地方,查相关资料时,感觉上传里面涉及到的内容还是比较多,于是就将上传这一块分为几节来处理,同时后续也会讲到关于做上传时遗漏的C#应该注意的地方,及时进行查漏补缺,尽量将这一块完善起来。

引入

上一节我们讲到了上传这一块,在评论中有园友提出未涉及到大文件的上传这一块,思前想后还是来试着做做,毕竟之前没怎么去仔细考虑过这个问题,尤其还可以联系实际开发中创建文件夹等一系列问题,同时关于上传在网上随便找找都充斥着大量的组件,我们何必再去造轮子,我需要做的是只是对基础的回顾以及进一步深入以及在做的过程中发现一些细节性的问题并解决就足矣,不喜勿喷。

深入上传

再次声明对于上传可以显示上传进度之类我们不去做过多探讨,有这样的组件,自行去找,我们只需实现比较核心的这一块即可。

我们可以想象这一样一个场景:比如在博客园中,每个博客者都可以上传文件如图片、脚本之类,我们可以通过园友名称来创建每个园友上传的文件,接下来我们来实现这样的一个场景。

既然是对应博客的名称创建文件,也就是需要对应的博客这样的一个类。如下:

    public class BlogSample
    {
        public string UserName { get; set; }

        public string Id { get; set; }
    }

我们通过博客名称来创建文件夹并在该文件夹下以唯一的Id来创建子文件夹,在该Id文件夹下的附件( atttachment )中存储上传的文件。接下来我们需要梳理整个上传文件的过程。难道就把要上传的文件直接到上传到对应的文件夹吗,这么做显然不是最优的,当有上传中断时则在文件夹创建的文件不是完整的则是垃圾文件,而我们直接先创建一个临时文件,即使上传失败我们可以定期清理临时文件也就是垃圾文件,若未中断,上传完毕时则将临时文件移动到我们对应的文件夹中。通过我们实际下载文件时很明显看的出也是这么做的。接下来我们开始进行实现。

(1)我们给出一个关于上传的 UploadManager 静态类,我们可以写死上传的文件夹名称或者通过配置文件自定义上传文件夹名称。

        static UploadManager()
        {
            //从配置文件中获取上传文件夹
            if (String.IsNullOrWhiteSpace(WebConfigurationManager.AppSettings["UploadFolder"]))
                UploadFolderRelativePath = @"~/upload";
            else
                UploadFolderRelativePath = WebConfigurationManager.AppSettings["UploadFolder"];

            UploadFolderPhysicalPath = HostingEnvironment.MapPath(UploadFolderRelativePath);

            if (!Directory.Exists(UploadFolderPhysicalPath))
                Directory.CreateDirectory(UploadFolderPhysicalPath);
        }

上述已经表明可以自定义上传文件夹在配置文件中(给出上传虚拟路径),例如如下:

  <!--<add key="UploadFolder" value="~/UploadFile/">-->

(2)保存文件的核心方法

        [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
        public static bool SaveFile(Stream stream, string fileName, string userName, string guid)
        {
            string tempPath = string.Empty, targetPath = string.Empty;

            try
            {
                string tempFileName = GetTempFilePath(fileName);

                if (userName != null)
                {
                    var contentType = userName;
                    var contentId = guid;

                    tempPath = GetTempFilePath(tempFileName);
                    targetPath = GetTargetFilePath(fileName, contentType, contentId, string.Empty, FilesSubdir);

                    //若上传文件夹中子文件夹未存在则创建
                    var file = new FileInfo(targetPath);
                    if (file.Directory != null && !file.Directory.Exists)
                        file.Directory.Create();

                    using (FileStream fs = File.Open(tempPath, FileMode.Append))
                    {
                        if (stream.Length > 0)
                        {
                            SaveFile(stream, fs);
                        }
                        fs.Close();
                    }
                    //上传完毕将临时文件移动到目标文件
                    File.Move(tempPath, targetPath);
                }
            }
            catch (Exception)
            {
                // 若上传出错,则删除上传到文件夹文件
                if (File.Exists(targetPath))
                    File.Delete(targetPath);

                // 删除临时文件
                if (File.Exists(tempPath))
                    File.Delete(tempPath);

                return false;
            }
            finally
            {
                // 删除临时文件
                if (File.Exists(tempPath))
                    File.Delete(tempPath);
            }
            return true;
        }

(3)循环读取流到文件流中

         /// <summary>
        /// 循环读取流到文件流中
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="fs"></param>
        public static void SaveFile(Stream stream, FileStream fs)
        {
            var buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)
            {
                fs.Write(buffer, 0, bytesRead);
            }
        }

(4)开始写入测试数据,进行调用方法:

            var testSample = new BlogSample() { UserName = "xpy0928", Id = Guid.NewGuid().ToString("N") };
            if (ModelState.IsValid)
            {
                var fileName = bModel.BlogPhoto.FileName;
                var success = UploadManager.SaveFile(bModel.BlogPhoto.InputStream, fileName, testSample.UserName, testSample.Id);
                if (!success)
                {
                    // TODO(your code)
                }
                //var filePath = Server.MapPath(string.Format("~/{0}", "File"));
                //bModel.BlogPhoto.SaveAs(Path.Combine(filePath, fileName));
                ModelState.Clear();
            }

接下来我们来进行测试,通过上传一个84M的文件来看看效果(稍等片刻,文件有点大)。

不好意思,令我大失所望,和昨天出现的错误不一样,今天出错是:超过最大请求长度。我们接下来再来看看昨天所说,我的IIS为10.0,也就是在IIS 7+上,通过昨天那样设置应该是没问题的,难道和另外一个设置有关吗,我们看看配置文件中的配置。

<httpRuntime targetFramework="4.5"/>

未进行设置,超过其默认设置28.6M就出错了吗,我们再设置为2G看看。

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

好,上传成功也未出现上述错误。

结语

这一节我们讲了一下利用流来进行大文件的处理,不过还是出现了一点小问题,和昨天再一起做一次总结:

(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>

关于在配置文件中如何设置文件大小而不出错,总算做了一个最终的总结,有收获,继续Fighting。

时间: 2024-07-28 21:21:47

ASP.NET MVC之文件上传【二】(九)的相关文章

ASP.NET MVC之文件上传【一】(八)

前言 这一节我们来讲讲在MVC中如何进行文件的上传,我们逐步深入,一起来看看. Upload File(一) 我们在默认创建的项目中的Home控制器下添加如下: public ActionResult UploadFile() { return View(); } [HttpPost] public ActionResult UploadFile(HttpPostedFileBase file) { var fileName = file.FileName; var filePath = Ser

探索Asp.net mvc 的文件上传(由浅入深)

代码下载:http://files.cnblogs.com/n-pei/mvcfileupload.zip 最近因为TeamVideo需要用到视频和图片上传功能,所以试着Google了很多资料,和大家分享下. 1.最基本的文件上传 在View界面通过Form把数据POST到控制端(Controller),Controller把文件存储到服务器,再Redirect到其他页面. View部分的代码: Controller部分需要判断是否有Post过来文件,有文件就保存,再重定向到index页面. 上

一起谈.NET技术,探索Asp.net mvc 的文件上传(由浅入深)

代码下载:http://files.cnblogs.com/n-pei/mvcfileupload.zip 最近因为TeamVideo需要用到视频和图片上传功能,所以试着Google了很多资料,和大家分享下. 1.最基本的文件上传 在View界面通过Form把数据POST到控制端(Controller),Controller把文件存储到服务器,再Redirect到其他页面. View部分的代码: Controller部分需要判断是否有Post过来文件,有文件就保存,再重定向到index页面. 上

ASP.NET MVC处理文件上传

在MVC应用中,文件的上传处理比较简单,下面是一个结合JQuery的例子. <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2>Files uploaded to server</h2> <div id="dialog" title="Upload files&qu

ASP.NET MVC处理文件上传的小例子_实用技巧

复制代码 代码如下: <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2>Files uploaded to server</h2> <div id="dialog" title="Upload files"> <% using (Html.B

mvc实现文件上传与下载

问题描述 mvc实现文件上传与下载 添加页面希望能够上传文件详情页面希望能够显示添加页面上传的文件,并且可以下载 请问如何实现,怎么将两者对应起来.查了很多资料都没有看懂,帮忙解决一下吧. 解决方案 http://www.cnblogs.com/CareySon/archive/2009/12/23/1630902.html 解决方案二: 首先你得知道,你想用哪种后台语言来处理文件的上传与下载. 解决方案三: 看你用什么框架来实现了,struts2还是springmvc?这两个都比较好用

asp.net中的文件上传控件能否打开一个固定文件夹然后再选择文件

问题描述 asp.net中的文件上传控件能否打开一个固定文件夹然后再选择文件asp.net中的文件上传控件能否打开一个固定文件夹然后再选择文件我现在要上传文件,但是在点击浏览的时候我想要打开一个指定的目录,然后在这个目录中选择文件..用什么方法能够实现呢?请各位大侠帮忙呀!!!!!!!!!??????????????????????????谢谢各位!!!!!!!! 解决方案 解决方案二:属于客户端程序,安全考虑的话怕不可行解决方案三:可以,将所选目录文件列出就行了,用常用的IO操作就能实现CSD

Spring MVC 多文件上传大小限制及异常处理

Spring MVC  多文件上传大小限制及异常处理 (包括 MaxUploadSizeExceededException 异常) 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. 补充如下: h

ASP.NET设计FTP文件上传的解决方案_实用技巧

如果要用ASP来作一个FTP文件上传的页面,我想很多人立刻就会想到要用第三方开发的组件,利用第三方的组件,虽然开发起来相对比较容易.但一般来说,免费下载的第三方的组件都有某些方面的功能限制,若要购买正版的第三方组件,对于国内的用户,花销也是一个不小的数字,就是能够承担的起,烦杂的手续也使很多人望而却步.虽然微软公司在本身的视窗系统里面也提供了一个可以用来上传文件的组件--Posting Acceptor.但用过这个组件的朋友们都有一种普遍的感觉,就是实在不好用. 现在好了,自从微软公司推出了.N