ASP.NET控件之FileUpload控件

使用 FileUpload 控件,可以为用户提供一种将文件从其计算机发送到服务器的方法。

可使用 FileUpload 控件执行下列操作:

使用户能够上载存储在服务器上的特定位置的文件。

限制可上载的文件的大小。

在存储上载的文件之前检查其属性。

FileUpload 控件使用户能够上载图片、文本文件或其他文件。FileUpload 控件显示一个文本框,在此用户可以键入希望上载到服务器的文件的名称。该控件还显示一个“浏览”按钮,该按钮显示一个文件导航对话框。(显示的对话框取决于用户计算机的操作系统。) 出于安全方面的考虑,不能将文件名预加载到 FileUpload 控件中。

处理上载的文件

当用户已选定要上载的文件并提交页时,该文件将作为请求的一部分上载。文件将被完整地缓存在服务器内存中。文件完成上载后,页代码开始运行。

可以通过下面的方式访问上载的文件:

作为在 FileUpload 控件的 FileBytes 属性中公开的字节数组。

作为在 FileContent 属性中公开的流。

作为 PostedFile 属性中类型 HttpPostedFile 的对象。PostedFile 对象公开一些属性,如 ContentType 和 ContentLength 属性,这些属性为您提供有关上载的文件的信息。

在代码运行时,可以检查文件的特征,例如文件的名称、大小和 MIME 类型,然后可以保存该文件。可以将文件当作字节数组或流来使用。另外,FileUpload 控件和 HttpPostedFile 对象都支持将文件写入磁盘的 SaveAs 方法。

对所上载文件的保存位置,没有固有限制。但是,若要保存文件,ASP.NET 进程必须具有在指定位置创建文件的权限。此外,还可能将应用程序配置为要求使用绝对路径(而不是相对路径)来保存文件,这是一种安全措施。如果将 httpRuntime 配置元素的 requireRootedSaveAsPath 属性设置为 true(默认值),则在保存上载的文件时必须提供绝对路径。

可以创建基于应用程序根文件夹的绝对路径,方法是使用 HttpServerUtility 类的 MapPath 方法,并将表示应用程序根文件夹的颚化符 (~) 传递给该方法。

可上载的最大文件的大小取决于 MaxRequestLength 配置设置的值。如果用户试图上载大于最大允许值的文件,则上载会失败。

在部分页更新中使用 FileUpload 控件

FileUpload 控件设计为仅用于回发方案,而不适用于部分页呈现期间的异步回发方案。当您在 UpdatePanel 控件内部使用 FileUpload 控件时,必须使用作为面板的一个 PostBackTrigger 对象的控件来上载文件。UpdatePanel 控件用于更新页的选定区域,而不是使用回发来更新整个页面。

安全性和 FileUpload 控件

通过使用 FileUpload 控件,用户可以上载可能存在恶意的文件,其中包含脚本文件和可执行文件。无法预先限制用户可以上载的文件。如果希望限制用户可以上载的文件的类型,则必须在上载文件后检查文件特征,如文件的文件扩展名和文件的 ContentType 属性的值。

在提交页面之前,可以使用客户端脚本来检查用户在文本框中键入的文件名。尽管在客户端执行文件名检查会很有用,但这并不能保证用户无法上载不安全的文件类型,如可执行文件。

使用 FileUpload Web 服务器控件上载文件

1.向页面添加 FileUpload 控件。

出于安全方面的考虑,不能将文件名预加载到 FileUpload 控件中。

2.在事件(如该页的 Load 事件)的处理程序中,执行下面的操作:

a.通过测试 FileUpload 控件的 HasFile 属性,检查该控件是否有上载的文件。

b.检查该文件的文件名或 MIME 类型以确保用户已上载了您要接收的文件。若要检查 MIME 类型,请获取作为 FileUpload 控件的 PostedFile 属性公开的 HttpPostedFile 对象。然后,通过查看已发送文件的 ContentType 属性,就可以获取该文件的 MIME 类型。

在某些情况下,已上载文件的 MIME 类型可能是伪造的,因此只检查文件的 MIME 类型不是一种可靠的安全检查。

c.将该文件保存到您指定的位置。您可以调用 HttpPostedFile 对象的 SaveAs 方法。或者,还可以使用 HttpPostedFile 对象的 InputStream 属性,以字节数组或字节流的形式管理已上载的文件。

下面的示例演示如何使用已上载的文件。该代码根据允许的文件扩展名的硬编码列表检查已上载文件的文件扩展名,并拒绝所有其他类型的文件。然后,将该文件写入当前网站的 UploadedImages 文件夹中。用已上载文件在客户端计算机上的文件名保存该文件。由于 HttpPostedFile 对象的 FileName 属性返回该文件在客户端计算机上的完整路径,因此会使用 FileUpload 控件的 FileName 属性。

请不要向用户显示所保存文件的路径和文件名;这样做可能会将有用的信息泄露给恶意用户。

protected void Page_Load(object sender, EventArgs e)
{
    if(IsPostBack)
    {
        Boolean fileOK = false;
        String path = Server.MapPath("~/UploadedImages/");
        if (FileUpload1.HasFile) 
        {
            String fileExtension = 
                System.IO.Path.GetExtension(FileUpload1.FileName).ToLower();
            String[] allowedExtensions = 
                {".gif", ".png", ".jpeg", ".jpg"};
          for (int i = 0; i < allowedExtensions.Length; i++)
          {
               if (fileExtension == allowedExtensions[i])
               {
                    fileOK = true;
               }
          }
        }
        if (fileOK)
        {
            try
            {
                FileUpload1.PostedFile.SaveAs(path 
                    + FileUpload1.FileName);
                Label1.Text = "File uploaded!";
            }
            catch (Exception ex)
            {
                Label1.Text = "File could not be uploaded.";
            }
        }
        else
        {
            Label1.Text = "Cannot accept files of this type.";
        }
    }
}