文件的上传下载是我们在实际项目开发过程中经常需要用到的技术,这里给出几种常见的方法,本文主要内容包括:
1、如何解决文件上传大小的限制
2、以文件形式保存到服务器
3、转换成二进制字节流保存到数据库以及下载方法
4、上传Internet上的资源

第一部分:
    首先我们来说一下如何解决ASP.NET中的文件上传大小限制的问题,我们知道在默认情况下ASP.NET的文件上传大小限制为2M,一般情况下,我们可以采用更改WEB.Config文件来自定义最大文件大小,如下:

<httpRuntime executionTimeout="300" maxRequestLength="40960" useFullyQualifiedRedirectUrl="false"/>

 

这样上传文件的最大值就变成了4M,但这样并不能让我们无限的扩大MaxRequestLength的值,因为ASP.NET会将全部文件载入内存后,再加以处理。解决的方法是利用隐含的HttpWorkerRequest,用它的GetPreloadedEntityBody和ReadEntityBody方法从IIS为ASP.NET建立的pipe里分块读取数据。实现方法如下:

1 IServiceProviderprovider=(IServiceProvider)HttpContext.Current;
 2 HttpWorkerRequestwr=(HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));
 3 byte[]bs=wr.GetPreloadedEntityBody();
 4 .
 5 if(!wr.IsEntireEntityBodyIsPreloaded())
 6 {
 7 intn=1024;
 8 byte[]bs2=newbyte[n];
 9 while(wr.ReadEntityBody(bs2,n)>0)
10 {
11 ..
12 }
13 }

这样就可以解决了大文件的上传问题了。

第二部分:
    下面我们来介绍如何以文件形式将客户端的一个文件上传到服务器并返回上传文件的一些基本信息
首先我们定义一个类,用来存储上传的文件的信息(返回时需要)。

1 public class FileUpLoad
 2 {
 3    public FileUpLoad()
 4    {
 5 
 6    }
 7 /**//// <summary>
 8         /// 上传文件名称
 9         /// </summary>
10         public string FileName
11         {
12             get
13             {
14                 return fileName;
15             }
16             set
17             {
18                 fileName = value;
19             }
20         }
21         private string fileName;
22 
23         /**//// <summary>
24         /// 上传文件路径
25         /// </summary>
26         public string FilePath
27         {
28             get
29             {
30                 return filepath;
31             }
32             set
33             {
34                 filepath = value;
35             }
36         }
37         private string filepath;
38 
39         
40         /**//// <summary>
41         /// 文件扩展名
42         /// </summary>
43         public string FileExtension
44         {
45             get
46             {
47                 return fileExtension;
48             }
49             set
50             {
51             
52                 fileExtension = value;
53             }
54                 
55         }
56         private string fileExtension;
57 }

 

另外我们还可以在配置文件中限制上传文件的格式(App.Config):

1 <?xml version="1.0" encoding="gb2312" ?>
2 <Application>    
3     <FileUpLoad>
4        <Format>.jpg|.gif|.png|.bmp</Format>
5     </FileUpLoad>
6 </Application>

这样我们就可以开始写我们的上传文件的方法了,如下:

1 public FileUpLoad UpLoadFile(HtmlInputFile InputFile,string filePath,string myfileName,bool isRandom)
 2         {
 3             
 4             FileUpLoad fp = new FileUpLoad();
 5 
 6             string fileName,fileExtension;
 7             string saveName;
 8             
 9             //
10             //建立上传对象
11             //
12             HttpPostedFile postedFile = InputFile.PostedFile;
13 
14             fileName        = System.IO.Path.GetFileName(postedFile.FileName);
15             fileExtension    = System.IO.Path.GetExtension(fileName);
16             
17             //
18             //根据类型确定文件格式
19             //
20             AppConfig app = new AppConfig();
21             string format = app.GetPath("FileUpLoad/Format");
22 
23 
24             //
25             //如果格式都不符合则返回
26             //
27             if(format.IndexOf(fileExtension)==-1)
28             {
29                 throw new ApplicationException("上传数据格式不合法");
30             }
31                 
32             //
33             //根据日期和随机数生成随机的文件名
34             //
35             if(myfileName != string.Empty)
36             {
37                 fileName = myfileName;            
38             }
39 
40             if(isRandom)
41             {
42                 Random objRand = new Random();
43                 System.DateTime date = DateTime.Now;
44                 //生成随机文件名
45                 saveName = date.Year.ToString() + date.Month.ToString() + date.Day.ToString() + date.Hour.ToString() + date.Minute.ToString() 
46 
47                     + date.Second.ToString() + Convert.ToString(objRand.Next(99)*97 + 100);
48                 fileName = saveName + fileExtension;
49             }
50             
51             string phyPath = HttpContext.Current.Request.MapPath(filePath);
52 
53 
54             //判断路径是否存在,若不存在则创建路径
55             DirectoryInfo upDir = new DirectoryInfo(phyPath);
56             if(!upDir.Exists)
57             {
58                 upDir.Create();
59             }
60 
61             //
62             //保存文件
63             //
64             try
65             {
66                 postedFile.SaveAs(phyPath + fileName);
67 
68                 fp.FilePath =  filePath  + fileName;
69                 fp.FileExtension = fileExtension;
70                 fp.FileName = fileName;
71             }
72             catch
73             {
74                 throw new ApplicationException("上传失败!");
75             }
76 
77 
78             //返回上传文件的信息
79             return fp;
80         
81         
82         }

然后我们在上传文件的时候就可以调用这个方法了,将返回的文件信息保存到数据库中,至于下载,就直接打开那个路径就OK了。

第三部分:
    这里我们主要说一下如何以二进制的形式上传文件以及下载。首先说上传,方法如下:

1 public byte[] UpLoadFile(HtmlInputFile f_IFile)
 2 {
 3          //获取由客户端指定的上传文件的访问
 4          HttpPostedFile upFile=f_IFile.PostedFile;
 5          //得到上传文件的长度
 6                 int upFileLength=upFile.ContentLength; 
 7          //得到上传文件的客户端MIME类型
 8                 string contentType = upFile.ContentType;
 9                 byte[] FileArray=new Byte[upFileLength];
10  
11                 Stream fileStream=upFile.InputStream; 
12                 
13                 fileStream.Read(FileArray,0,upFileLength);
14         
15         return FileArray;
16 
17 }

 

这个方法返回的就是上传的文件的二进制字节流,这样我们就可以将它保存到数据库了。下面说一下这种形式的下载,也许你会想到这种方式的下载就是新建一个aspx页面,然后在它的Page_Load()事件里取出二进制字节流,然后再读出来就可以了,其实这种方法是不可取的,在实际的运用中也许会出现无法打开某站点的错误,我一般采用下面的方法:

首先,在Web.config中加入:


1 <add verb="*" path="openfile.aspx" type="RuixinOA.Web.BaseClass.OpenFile, RuixinOA.Web"/>

 

这表示我打开openfile.aspx这个页面时,系统就会自动转到执行RuixinOA.Web.BaseClass.OpenFile 这个类里的方法,具体实现如下:

1 using System;
 2 using System.Data;
 3 using System.Web;
 4 using System.IO;
 5 using Ruixin.WorkFlowDB;
 6 using RXSuite.Base;
 7 using RXSuite.Component;
 8 using RuixinOA.BusinessFacade;
 9 
10 namespace RuixinOA.Web.BaseClass
11 {
12     /**//// <summary>
13     /// NetUFile 的摘要说明。
14     /// </summary>
15     public class OpenFile : IHttpHandler
16     {
17         public void ProcessRequest(HttpContext context) 
18         {
19             
20             //从数据库中取出要下载的文件信息
21             RuixinOA.BusinessFacade.RX_OA_FileManager os = new RX_OA_FileManager();
22             EntityData data = os.GetFileDetail(id);
23 
24             if(data != null && data.Tables["RX_OA_File"].Rows.Count > 0)
25             {
26                 DataRow dr = (DataRow)data.Tables["RX_OA_File"].Rows[0];
27 
28                 context.Response.Buffer = true;
29                 context.Response.Clear();
30                 context.Response.ContentType = dr["CContentType"].ToString(); 
31                 context.Response.AddHeader("Content-Disposition","attachment;filename=" + HttpUtility.UrlEncode(dr["CTitle"].ToString()));
32                 context.Response.BinaryWrite((Byte[])dr["CContent"]);
33                 context.Response.Flush();
34                 context.Response.End();
35             }
36                         
37 
38         }
39 
40         public bool IsReusable 
41         { 
42 
43             get { return true;} 
44         }
45     }
46 }
47

执行上面的方法后,系统会提示用户选择直接打开还是下载。这一部分我们就说到这里。

第四部分:

    这一部分主要说如何上传一个Internet上的资源到服务器。前面我们有一篇文章详细介绍了使用方法,这里我不再多说。
请参考:将动态页面转化成二进制字节流
第五部分: 多文件上传

 

在以前的Web应用中,上传文件是个很麻烦的事,现在有了.NET,文件上传变得轻而易举。下面的这个例子实现了多文件上传功能。可以动态添加输入表单,上传的文件数量没有限制。代码如下:

 aspx代码

1 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="MultiFileUpload.aspx.cs"
 2   Inherits="MultiFileUpload" %>
 3 
 4 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 5 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 6 <html xmlns="http://www.w3.org/1999/xhtml">
 7 <head runat="server">
 8   <title>孟宪会多文件上传测试</title>
 9 
10   <script type="text/javascript">
11     function addFile() {
12       var div = document.createElement("div");
13       var f = document.createElement("input");
14       f.setAttribute("type", "file")
15       f.setAttribute("name", "File")
16       f.setAttribute("size", "50")
17       div.appendChild(f)
18       var d = document.createElement("input");
19       d.setAttribute("type", "button")
20       d.setAttribute("onclick", "deteFile(this)");
21       d.setAttribute("value", "移除")
22       div.appendChild(d)
23       document.getElementById("_container").appendChild(div);
24     }
25 
26     function deteFile(o) {
27       while (o.tagName != "DIV") o = o.parentNode;
28       o.parentNode.removeChild(o);
29     }
30   </script>
31 
32 </head>
33 <body>
34   <form id="form1" runat="server" method="post" enctype="multipart/form-data">
35   <h3>多文件上传</h3>
36    用户名:<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
37   <div id="_container">
38     <input type="file" size="50" name="File" />
39   </div>
40   <div>
41     <input type="button" value="添加文件(Add)" onclick="addFile()" />
42   </div>
43   <div style="padding:10px 0">
44     <asp:Button runat="server" Text="开始上传" ID="UploadButton" 
45       onclick="UploadButton_Click"></asp:Button>
46   </div>
47   <div>
48     <asp:Label ID="strStatus" runat="server" Font-Names="宋体" Font-Bold="True" Font-Size="9pt"
49       Width="500px" BorderStyle="None" BorderColor="White"></asp:Label>
50   </div>
51   </form>
52 </body>
53 </html>
54 
55

 

 

 aspx.cs代码

1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.UI;
 6 using System.Web.UI.WebControls;
 7 
 8 public partial class MultiFileUpload : System.Web.UI.Page
 9 {
10     protected void UploadButton_Click(object sender, EventArgs e)
11     {
12       ///'遍历File表单元素
13       HttpFileCollection files = HttpContext.Current.Request.Files;
14 
15       /// '状态信息
16       System.Text.StringBuilder strMsg = new System.Text.StringBuilder("您输入的用户名是:" + TextBox1.Text + "<br/>");
17       strMsg.Append("上传的文件分别是:<hr color='red'/>");
18       try
19       {
20         for (int iFile = 0; iFile < files.Count; iFile++)
21         {
22           ///'检查文件扩展名字
23           HttpPostedFile postedFile = files[iFile];
24           string fileName, fileExtension;
25           fileName = System.IO.Path.GetFileName(postedFile.FileName);
26           if (fileName != "")
27           {
28             fileExtension = System.IO.Path.GetExtension(fileName);
29             strMsg.Append("上传的文件类型:" + postedFile.ContentType.ToString() + "<br>");
30             strMsg.Append("客户端文件地址:" + postedFile.FileName + "<br>");
31             strMsg.Append("上传文件的文件名:" + fileName + "<br>");
32             strMsg.Append("上传文件的扩展名:" + fileExtension + "<br><hr>");
33             ///'可根据扩展名字的不同保存到不同的文件夹
34             ///注意:可能要修改你的文件夹的匿名写入权限。
35             postedFile.SaveAs(System.Web.HttpContext.Current.Request.MapPath("images/") + fileName);
36           }
37         }
38         strStatus.Text = strMsg.ToString();
39       }
40       catch (System.Exception Ex)
41       {
42         strStatus.Text = Ex.Message;
43       }
44 
45     }
46 }
47 
48

 

第六部分:总结
    今天简单的介绍了几种文件上传与下载的方法,都是在实际的项目开发中经常需要用到的,可能还有不完善的地方,希望大家可以互相交流一下项目开发中的经验。写的不好的地方,请指正,谢谢!

 

参考文章:http://blog.ncmem.com/wordpress/2023/09/13/asp-net中常用的文件上传下载方法/