FileUpload控件

  • FileUpLoad控件用于用户向Web应用程序上传文件。文件上传后,可以把文件保存在任意地方,通常把文件保存在文件系统或数据库。向页面添加FileUpLoad控件会自动地为服务器的<form>标签添加enctype="multipart/form-data"属性。

    1.  把文件保存到文件系统

    • 以下代码页面展示了如何使用FileUpLoad控件把图片上传到应用程序。
      [c-sharp] view plain copy print ?
      1. <%@ Page Language="C#" %> 
      2. <%@ Import Namespace="System.IO" %> 
      3. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
      4. <script runat="server"
      5.     protected void btnAdd_Click(object sender, EventArgs e) 
      6.     { 
      7.         if (upImage.HasFile) 
      8.         { 
      9.             if (CheckFileType(upImage.FileName)) 
      10.             { 
      11.                 //用FileUpload.FileName属性得到上传文件名,也可以使用HttpPostedFile.FileName得到。 
      12.                 string filePath = "~/UploadImages/" + upImage.FileName; 
      13.                 //MapPath方法,检索虚拟路径(绝对的或相对的)或应用程序相关的路径映射到的物理路径。 
      14.                 //FileUpload.SavaAs()方法用于把上传文件保存到文件系统中,也可以使用HttpPostedFile.SaveAs()方法。 
      15.                 upImage.SaveAs(MapPath(filePath)); 
      16.             } 
      17.         } 
      18.     } 
      19.     bool CheckFileType(string fileName) 
      20.     { 
      21.         //GetExtension()方法返回指定的路径字符串的扩展名。 
      22.         //Path类位于System.IO命名空间中,用于对包含文件或目录路径信息的 String 实例执行操作。 
      23.         string ext = Path.GetExtension(fileName); 
      24.         switch (ext.ToLower()) 
      25.         { 
      26.             case ".gif": return true
      27.             case ".png": return true
      28.             case ".jpg": return true
      29.             case ".jpeg": return true
      30.             default: return false
      31.         } 
      32.     } 
      33.     void Page_PreRender() 
      34.     { 
      35.         string upFolder = MapPath("~/UploadImages/"); 
      36.         //在指定的路径中初始化DirectoryInfo类的新实例,DirectoryInfo类公开用于创建、移动和枚举目录和子目录的实例方法。 
      37.         DirectoryInfo dir = new DirectoryInfo(upFolder); 
      38.         //GetFiles,返回当前目录的文件列表。 
      39.         dlstImages.DataSource = dir.GetFiles(); 
      40.         dlstImages.DataBind(); 
      41.     } 
      42. </script> 
      43.  
      44. <html xmlns="http://www.w3.org/1999/xhtml"
      45. <head runat="server"
      46.     <title>无标题页</title> 
      47. </head> 
      48. <body> 
      49.     <form id="form1" runat="server"
      50.     <div> 
      51.         <asp:Label ID="lblImageFile" runat="server" Text="Image File" AssociatedControlID="upImage"></asp:Label> 
      52.         <asp:FileUpload ID="upImage" runat="server" /><br /> 
      53.         <asp:Button ID="btnAdd" runat="server" Text="Add Image" OnClick="btnAdd_Click"/><hr /> 
      54.         <asp:DataList ID="dlstImages" RepeatColumns="3" runat="server"
      55.             <ItemTemplate> 
      56.                 <asp:Image ID="Image1" runat="server" style="width:200px" 
      57.                     ImageUrl='<%# Eval("Name","~/UploadImages/{0}") %>' /> 
      58.                  <br /> 
      59.                  <%# Eval("Name") %> 
      60.                  <!--Name,对于文件,获取该文件的名称。对于目录,如果存在层次结构,则获取层次结构中最后一个目录的名称。否则,Name 属性获取该目录的名称。 --> 
      61.             </ItemTemplate> 
      62.         </asp:DataList> 
      63.     </div> 
      64.     </form> 
      65. </body> 
      66. </html> 
      效果:

      为在系统中保存文件,asp.net页面关联的Windows帐户必须有足够的权限来保存文件。

    2.  把文件保存到数据库

    • 也可以用FileUpload控件把文件保存到数据库表。在数据库中保存和检索文件会给服务器增加更多压力。但是它也有些优点,首先,可以避免系统权限问题,其次,能更方便地备份信息。下面演示的是如何把Word文档保存到数据库表中。
      [c-sharp] view plain copy print ?
      1. <%@ Page Language="C#" %> 
      2. <%@ Import Namespace="System.IO" %> 
      3. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
      4.  
      5. <script runat="server"
      6.     protected void btnAdd_Click(object sender, EventArgs e) 
      7.     { 
      8.         if (upFile.HasFile) 
      9.         { 
      10.             //调用SqlDataSource控件的Insert()方法把FileUpLoad控件的FileName和FileBytes属性的值插入本地SQL Express数据库表。 
      11.             //Insert()方法使用InsertCommand SQL字符串和InsertParameters集合中的所有参数执行插入操作。 
      12.             if (CheckFileType(upFile.FileName)) 
      13.                 srcFiles.Insert(); 
      14.         } 
      15.     } 
      16.     bool CheckFileType(string fileName) 
      17.     { 
      18.         return Path.GetExtension(fileName).ToLower() == ".doc"
      19.     } 
      20. </script> 
      21.  
      22. <html xmlns="http://www.w3.org/1999/xhtml"
      23. <head runat="server"
      24.     <title>无标题页</title> 
      25. </head> 
      26. <body> 
      27.     <form id="form1" runat="server"
      28.     <div> 
      29.         <asp:Label ID="lblFile" runat="server" AssociatedControlID="upFile" Text="Word Document"></asp:Label> 
      30.         <asp:FileUpload ID="upFile" runat="server" /> 
      31.         <asp:Button ID="btnAdd" runat="server" Text="Add Document" OnClick="btnAdd_Click" /><hr /> 
      32.          
      33.         <asp:Repeater ID="rptFiles" DataSourceID="srcFiles" runat="server"
      34.         <ItemTemplate><li> 
      35.         <asp:HyperLink ID="lnkFile" Text='<%Eval("FileName")%>' NavigateUrl='<%Eval("Id","~/FileHandler.ashx?id={0}") %>' runat="server" /></li> 
      36.         </ItemTemplate> 
      37.         </asp:Repeater> 
      38.          
      39.         <asp:SqlDataSource ID="srcFiles" runat="server" 
      40.             ConnectionString="Server=./SQLExpress;Integrated Security=True; 
      41.             AttachDbFilename=|DataDirectory|FilesDB.mdf;User Instance=True" 
      42.             SelectCommand="select Id,FileName from Files" 
      43.             InsertCommand="insert Files(FileName,FileBytes) values (@FileName,@FileBytes)"
      44.             <InsertParameters> 
      45.                <asp:ControlParameter Name="FileName" ControlID="upFile" PropertyName="FileName" /> 
      46.                <asp:ControlParameter Name="FileBytes" ControlID="upFile" PropertyName="FileBytes" /> 
      47.             </InsertParameters> 
      48.         </asp:SqlDataSource> 
      49.         <!--InsertParameters从与SqlDataSource控件相关联的对象获取包含InsertCommand属性所使用的参数的参数集合。--> 
      50.         <!--ControlParameter对象用于将参数设置为ASP.NET网页中的控件的属性值。 
      51.             使用ControlID属性指定控件。使用PropertyName属性指定提供参数值的属性的名称。--> 
      52.         <!--FileBytes以字节数组形式获取上传文件内容。--> 
      53.     </div> 
      54.     </form> 
      55. </body> 
      56. </html> 

      效果:

      页面显示了当前在数据库中Word文档的列表。可以点击其中的文件查看文件内容。点击文档名会链接到FileHandler.ashx页面,这个文件是一个普通的HTTP处理程序文件。当有人用特定的路径请求文件时,HTTP处理程序用于执行代码。下面是FileHandler.ashx文件的代码。
      [c-sharp] view plain copy print ?
      1. <%@ WebHandler Language="C#" Class="FileHandler" %> 
      2. using System; 
      3. using System.Web; 
      4. using System.Data; 
      5. using System.Data.SqlClient; 
      6. public class FileHandler : IHttpHandler { 
      7.     const string conString = @"Server=./SQLExpress;Integrated Security=True; 
      8.         AttachDbFileName=|DataDirectory|FilesDB.mdf;User Instance=True";  
      9.     public void ProcessRequest (HttpContext context) { 
      10.         context.Response.ContentType = "application/msword";       
      11.         SqlConnection con = new SqlConnection(conString); 
      12.         SqlCommand cmd = new SqlCommand("SELECT FileBytes FROM Files WHERE Id=@Id", con); 
      13.         cmd.Parameters.AddWithValue("@Id", context.Request["Id"]); 
      14.         using (con) 
      15.         { 
      16.             con.Open(); 
      17.             byte[] file = (byte[])cmd.ExecuteScalar(); 
      18.             context.Response.BinaryWrite(file); 
      19.         } 
      20.     } 
      21.     public bool IsReusable { 
      22.         get
      23.             return false
      24.         } 
      25.     } 
      26.  
      当请求FileHandler.ashx页面时,执行了ProcessRequest()方法。该方法取得名为Id的查询字符串项,并从数据库表Files中获取匹配的记录。数据库记录包含Word文档内容字节数组。再用Response.BinaryWrite()方法把字节数组发送到浏览器。
      关于HTTP处理程序,现在还没学,上面的FileHandler.ashx页面的代码大部分都不太理解,等以后学到之方面的内容了,再回来解析一下吧。

    3.  上传大文件

    • 上传大文件时,需要做一些额外工作。你可能不希望把服务器端的所有内存都消耗在容纳整个文件上。处理大文件时,需要使用多个可托管(manageable)内存块来处理文件。
      首先,为了处理大文件需要配置应用程序。有两个配置项影响着向服务器提交大文件:httpRuntime maxRequestLength和httpRuntime requestLengthDiskThreshold。maxRequestLength指定提交的表单能被服务器端接收的最大值。默认不能提交大于4MB的表单,否则会得到一个异常。如果要上传超过4MB的文件就需要更改该配置。requestLengthDiskThreshold决定如何把上表单缓存在文件系统。asp.net framework可以把大的文件缓存在文件系统中,当文件大小超过requestLengthDiskThreshold设置后,文件的余下部分被缓存在文件系统(asp.net临时文件夹中)。默认情况下,把超过80KB的提交数据缓存到文件缓存器中,可以修改requestLengthDiskThreshold来设置新的阈值(requestLengthDiskThreshold设置的值必须小于maxRequestLength设置值)。下面代码的Web配置文件设置为可以上传不超过10MB的文件,并把缓存阈值改为100kB。
      <configuration>
        <system.web>
          <httpRuntime maxRequestLength="10240" requestLengthDiskThreshold="100"/>
        </system.web>
      </configuration>
      下面代码演示如何高效地把一个大文件存储到数据库表中。
      [c-sharp] view plain copy print ?
      1. <%@ Page Language="C#" %> 
      2. <%@ Import Namespace="System.IO" %> 
      3. <%@ Import Namespace="System.Data" %> 
      4. <%@ Import Namespace="System.Data.SqlClient" %> 
      5. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
      6. <script runat="server"
      7.     const string conString = @"Server=./SQLExpress;Integrated Security=True;AttachDbFilename=|DataDirectory|FilesDB.mdf;User Instance=True"
      8.     //@在c#中表示后面的字符串强制不转义,在里面的转义字符无效 
      9.     void btnAdd_Click(object sender, EventArgs e) 
      10.     { 
      11.         if (upFile.HasFile) 
      12.         { 
      13.             if (CheckFileType(upFile.FileName)) 
      14.             { 
      15.                 AddFile(upFile.FileName, upFile.FileContent); 
      16.                 //FileUpload.FileContent以流(stream)形式获取上传文件内容。 
      17.                 rptFiles.DataBind(); 
      18.             } 
      19.         } 
      20.     } 
      21.     bool CheckFileType(string fileName) 
      22.     { 
      23.         return Path.GetExtension(fileName).ToLower() == ".doc"
      24.     } 
      25.     //Stream类是所有流的抽象基类,提供字节序列的一般视图。 
      26.     void AddFile(string fileName, Stream upload) 
      27.     { 
      28.         SqlConnection con = new SqlConnection(conString); 
      29.         SqlCommand cmd = new SqlCommand("INSERT Files (FileName) Values (@FileName);" + "SELECT @Identity=SCOPE_IDENTITY()", con); 
      30.         //SELECT @Identity=SCOPE_IDENTITY()声明一个参数,在后面传入一个值,可以避免SQL注入,比直接拼SQL语句好 
      31.         //获取添加记录的自增ID。 
      32.         cmd.Parameters.AddWithValue("@FileName", fileName); 
      33.         //SqlCommand.Parameters用于获取SqlParameterCollection。 
      34.         //SqlParameterCollection表示与 SqlCommand 相关联的参数的集合以及各个参数到 DataSet 中列的映射。 
      35.         //AddWithValue将一个值添加到 SqlParameterCollection 的末尾。 
      36.         SqlParameter idParm = cmd.Parameters.Add("@Identity", SqlDbType.Int); 
      37.         idParm.Direction = ParameterDirection.Output; 
      38.  
      39.         using (con) 
      40.         { 
      41.             con.Open(); 
      42.             cmd.ExecuteNonQuery(); 
      43.             int newFileId = (int)idParm.Value; 
      44.             StoreFile(newFileId, upload, con); 
      45.         } 
      46.         //在using作用域之后自动释放对象(调用Dispose方法),相当于con.close()。 
      47.     } 
      48.      
      49.     void StoreFile(int fileId, Stream upload, SqlConnection connection) 
      50.     { 
      51.         //从流br内读取长度为8040的数据 
      52.         int bufferLen = 8040; 
      53.         BinaryReader br = new BinaryReader(upload); 
      54.         byte[] chunk = br.ReadBytes(bufferLen); 
      55.          
      56.         //修改数据表Files内Id为fileId的数据流为chunk 
      57.         SqlCommand cmd = new SqlCommand("UPDATE Files SET FileBytes=@Buffer WHERE Id=@FileId", connection); 
      58.         cmd.Parameters.AddWithValue("@FileId", fileId); 
      59.         cmd.Parameters.Add("@Buffer", SqlDbType.VarBinary, bufferLen).Value = chunk; 
      60.         cmd.ExecuteNonQuery(); 
      61.  
      62.         //###AAA###追加数据表Files内Id为fileId的数据流 
      63.         SqlCommand cmdAppend = new SqlCommand("UPDATE Files SET FileBytes .WRITE(@Buffer, NULL, 0) WHERE Id=@FileId", connection); 
      64.         cmdAppend.Parameters.AddWithValue("@FileId", fileId); 
      65.         cmdAppend.Parameters.Add("@Buffer", SqlDbType.VarBinary, bufferLen); 
      66.         chunk = br.ReadBytes(bufferLen); 
      67.  
      68.         //当br流中有可读数据时,追加至###AAA### 
      69.         while (chunk.Length > 0) 
      70.         { 
      71.             cmdAppend.Parameters["@Buffer"].Value = chunk; 
      72.             cmdAppend.ExecuteNonQuery(); 
      73.             chunk = br.ReadBytes(bufferLen); 
      74.         } 
      75.         br.Close(); //关闭流 
      76.     } 
      77. </script> 
      78.  
      79. <html xmlns="http://www.w3.org/1999/xhtml"
      80. <head runat="server"
      81.     <title>无标题页</title> 
      82. </head> 
      83. <body> 
      84.     <form id="form1" runat="server"
      85.     <div> 
      86.     <asp:Label ID="lblFile" runat="server" AssociatedControlID="upFile" Text="Word Document"></asp:Label> 
      87.         <asp:FileUpload ID="upFile" runat="server" /> 
      88.         <asp:Button ID="btnAdd" runat="server" Text="Add Document" OnClick="btnAdd_Click" /><hr /> 
      89.          
      90.         <asp:Repeater ID="rptFiles" DataSourceID="srcFiles" runat="server"
      91.         <ItemTemplate> 
      92.         <li> 
      93.         <asp:HyperLink ID="lnkFile" Text='<%#Eval("FileName")%>' NavigateUrl='<%#Eval("Id","~/FileHandlerLarge.ashx?id={0}") %>' runat="server" /> 
      94.         </li> 
      95.         </ItemTemplate> 
      96.         </asp:Repeater> 
      97.          
      98.         <asp:SqlDataSource ID="srcFiles" runat="server" 
      99.             ConnectionString="Server=./SQLExpress;Integrated Security=True; 
      100.             AttachDbFilename=|DataDirectory|FilesDB.mdf;User Instance=True" 
      101.             SelectCommand="select Id,FileName from Files"
      102.         </asp:SqlDataSource> 
      103.     </div> 
      104.     </form> 
      105. </body> 
      106. </html> 
      在上面代码中,首先调用了AddFile()方法,该方法在包含文件名字段的数据库表Files中新增一行。然后调用StoreFile()方法,该方法把上传文件的实际字节添加到数据库中。上传文件被分成8040字节大小的块。注意在更新数据库字段FileBytes时,SQL UPDATE语句包含.WRITE字句。该代码中的页面不会在内存中装整个上传文件,上传文件以8040字节大小的块从文件系统中取出,产一块一块存入SQL Server中。
      点击文件名将执行FileHandle.aspx HTTP处理程序,该项处理程序从数据库中获取先中的文件并把它发送到浏览器。下面代码包含了这个处理程序。
      [c-sharp] view plain copy print ?
      1. <%@ WebHandler Language="C#" Class="FileHandlerLarge" %> 
      2. using System; 
      3. using System.Web; 
      4. using System.Data; 
      5. using System.Data.SqlClient; 
      6. public class FileHandlerLarge : IHttpHandler { 
      7.     const string conString = @"Server=./SQLExpress;Integrated Security=True; 
      8.         AttachDbFileName=|DataDirectory|FilesDB.mdf;User Instance=True"; 
      9.     public void ProcessRequest (HttpContext context) { 
      10.         context.Response.Buffer = false
      11.         context.Response.ContentType = "application/msword"
      12.         SqlConnection con = new SqlConnection(conString); 
      13.         SqlCommand cmd = new SqlCommand("SELECT FileBytes FROM Files WHERE Id=@Id", con); 
      14.         cmd.Parameters.AddWithValue("@Id", context.Request["Id"]); 
      15.         using (con) 
      16.         { 
      17.             con.Open(); 
      18.             SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess); 
      19.             if (reader.Read()) 
      20.             { 
      21.                 int bufferSize = 8040; 
      22.                 byte[] chunk = new byte[bufferSize]; 
      23.                 long retCount; 
      24.                 long startIndex = 0; 
      25.  
      26.                 retCount = reader.GetBytes(0, startIndex, chunk, 0, bufferSize); 
      27.  
      28.                  
      29.                 while (retCount == bufferSize) 
      30.                 { 
      31.                     context.Response.BinaryWrite(chunk); 
      32.  
      33.                     startIndex += bufferSize; 
      34.                     retCount = reader.GetBytes(0, startIndex, chunk, 0, bufferSize); 
      35.                 } 
      36.  
      37.                 byte[] actualChunk = new Byte[retCount - 1]; 
      38.                 Buffer.BlockCopy(chunk, 0, actualChunk, 0, (int)retCount - 1); 
      39.                 context.Response.BinaryWrite(actualChunk); 
      40.                                 
      41.             } 
      42.         } 
      43.     } 
      44.   
      45.     public bool IsReusable { 
      46.         get
      47.             return false
      48.         } 
      49.     } 
      50.  
      上面代码中的HTTP处理程序使用SqlDataReader从数据库中获取文件。注意,SqlDataReader使用CommandBehavior.SequentialAccess参数获取数据。这个参数使SqlDataReader以流的方式加载数据。数据库字段的内容以8040字节大小的块取入内存中,这些内容块用Response.BinaryWrite()方法写入浏览器。另外注意这个处理程序禁止用了响应缓存,Response.Buffer属性的值被设成False。由于禁用了缓存,处理程序输出就不会在传输到浏览器前缓在服务器端的内存中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值