65.9K
CodeProject 正在变化。 阅读更多。
Home

ASP.NET 中的文件系统浏览:新方法与旧方法的对比

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.21/5 (19投票s)

2005年7月3日

3分钟阅读

viewsIcon

144660

downloadIcon

3470

从 ASP 迁移到 ASP.NET 的大多数程序员仍然使用循环创建的方法来显示特定文件夹的内容。在本演示中,我将向您展示如何使用文件系统对象、DataGrid 和 DataTable 来完成此任务。

引言

“文件系统浏览?那是什么鬼?”

“旧方法?新方法?还有其他方法吗???”

我想我们大多数人仍然处于 .NET 之前的思维模式,我经常用这个术语来形容那些基于过去做事方式而没有利用新技术优势来简化任务的解决方案。这种思维模式的一个绝佳例子就是,当您被要求创建一个 Web 窗体来列出文件夹内容并允许用户下载该文件夹中选定的文件时,您的脑海中会浮现出什么?我敢打赌,80% 以上的程序员会给出这样的答案。

“是的,我可以构建一个函数来读取文件夹,并像我在 ASP 3.0 中那样编写它,使用 HTML 标签构建布局,然后遍历指定文件夹内的所有目录和文件。然后,我将使用 Response.Write 方法将表格结构写入 HTML 页面。”

有罪??

我想我们大多数人仍然这样想……

如果我告诉您,您可以通过仅使用一些 System.IO 对象、一个 DataTable 和一个 DataGrid 来完成此任务,您会怎么想?听起来很奇怪,对吧?但这是真的!在继续讲解解决方案之前,我想向您展示一个由 ASP.NET 程序员编写的、使用旧方法完成此任务的代码示例。

这是经典代码的 C# 示例

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Text;
using System.IO;
using System.Configuration;
namespace KeithRull.FolderBrowserCS
{
    /// <summary>

    /// Summary description for FolderBrowser.

    /// </summary>

    public class theOldWayBrowser : System.Web.UI.Page
    {
        protected System.Web.UI.WebControls.PlaceHolder plhFiles;
        
        private void Page_Load(object sender, System.EventArgs e)
        {
            //create the our table

            LiteralControl lcTableHead = new 
                       LiteralControl(@"<TABLE id=FileSystem" + 
                       @"style='FONT-SIZE: xx-small;" + 
                       @"BORDER-TOP-STYLE: none;" + 
                       @"FONT-FAMILY: Arial;" + 
                       @"BORDER-RIGHT-STYLE: none;" + 
                       @"BORDER-LEFT-STYLE: none;" + 
                       @"BORDER-COLLAPSE: collapse;" + 
                       @"BORDER-BOTTOM-STYLE: none'" + 
                       @"cellSpacing=0" + 
                       @"rules=all border=1>");
            plhFiles.Controls.Add(lcTableHead);
            LiteralControl lcContents;
            
            //creathe the column headers

            LiteralControl lcTableHeader = new 
                   LiteralControl(@"<TR>" +
                   @"<TD style='WIDTH: 80px'>Type</TD>" +
                   @"<TD style='WIDTH: 350px'>Name</TD>" +
                   @"<TD style='WIDTH: 150px'>CreationTime</TD>" +
                   @"<TD style='WIDTH: 150px'>LastWriteTime</TD>" +
                   @"</TR>");
            plhFiles.Controls.Add(lcTableHeader);
            try 
            {
                //read our query string, if its null, 

                //assign the default folder

                //to our variable else assign the query string value. 

                string strDir = Request.QueryString["d"] == null ? 
                   FileBrowerProperty.IntialPath : Request.QueryString["d"];
                //read the directory

                DirectoryInfo DirInfo = new DirectoryInfo(strDir);
                //read the subdirectories inside the parent directory

                DirectoryInfo[] subDirs = DirInfo.GetDirectories();
                //read the files in the parent directory

                FileInfo[] Files = DirInfo.GetFiles();
                //check if there are directories and 

                //files inside our parent directory

                if((Files.Length != 0) && (subDirs.Length!=0))
                {
                    //loop thru each of the directory 

                    //inside the parent directory

                    foreach(DirectoryInfo di in subDirs)
                    {
                        //add the directory info to our table

                        LiteralControl lcFolders = 
                                 new LiteralControl(@"<TR>" + 
                                 @"<TD style='WIDTH: 80px'>" + 
                                 @"Directory</TD>" + 
                                 @"<TD style='WIDTH: 350px'>" + 
                                 @"<a href='theOldWayBrowser.aspx?d=" + 
                                 @di.FullName + "'>" + di.Name + 
                                 "</a></TD><TD style='WIDTH: 150px'>" + 
                                 di.CreationTime + 
                                 "</TD><TD style='WIDTH: 150px'>" + 
                                 di.LastWriteTime + "</TD></TR>");
                        plhFiles.Controls.Add(lcFolders);
                    }
                    //loop thru each of the file 

                    //inside the parent directory

                    foreach(FileInfo fi in Files)
                    {
                        //add the file info to our table

                        LiteralControl lcContentsHead = 
                           new LiteralControl("<tr><td>File</td><td>");
                        plhFiles.Controls.Add(lcContentsHead); 
                        LinkButton lb = new LinkButton();
                        //set the label and command name 

                        //to the filename of the file

                        lb.Text = @fi.Name;
                        lb.CommandName = @fi.Name;
                        //set the command argument to the fullpath

                        lb.CommandArgument = @fi.FullName;
                        //add our handler

                        lb.Click += new EventHandler(Download);
                        plhFiles.Controls.Add(lb);
                        LiteralControl lcContentsTail = 
                               new LiteralControl("</td><td>" + 
                               fi.CreationTime + 
                               "</td><td valign='bottom'>"+ 
                               fi.LastWriteTime+"</td></tr>");
                        plhFiles.Controls.Add(lcContentsTail);
                    }
                }
                else
                {
                    // there is file or folder inside the directory

                    lcContents = 
                          new LiteralControl("<tr>" +
                          "<td colspan = 4>" + 
                          "No file/folder found inside this " + 
                          "directory.</td></tr>");
                    plhFiles.Controls.Add(lcContents);
                } 
            }
            catch(Exception ex)
            {
                //error trap

                lcContents = 
                    new LiteralControl("<tr>" + 
                    "<td colspan = 4> Error encountered" + 
                    " while trying to parse directory. " + 
                    ex.Message + "</td></tr>");
                plhFiles.Controls.Add(lcContents);
            }
            LiteralControl lcTableTail = 
                new LiteralControl("</table>");
            plhFiles.Controls.Add(lcTableTail);
        }
        private void Download(object sender, System.EventArgs e)
        {
            //get the file path

            string filepath = ((LinkButton) sender).CommandArgument;
            //geth the filename

            string filename = ((LinkButton) sender).CommandName;
            
            //read the file to our stream

            Stream s = File.OpenRead(filepath);
            //create the bytes to be streamed

            Byte[] buffer = new Byte[s.Length];
            
            //build the buffer

            try 
            { 
                s.Read(buffer, 0, (Int32) s.Length); 
            }
            //close our stream

            finally { s.Close(); }
            //clear the response headers

            Response.ClearHeaders();
            //clear the content type

            Response.ClearContent();
            Response.ContentType = "application/octet-stream";
            //add our header

            Response.AddHeader("Content-Disposition", 
                "attachment; filename=" + filename);
            //write the buffer to the http stream

            Response.BinaryWrite(buffer);
            //end response

            Response.End();
        }
    }
}

这看起来不像旧的 ASP 实现吗?在读取数据时还在与界面打交道?

正如我刚才所说,我们可以通过使用 DataTableDataGrid 来完成相同的任务。首先,让我们稍微检查一下 DataGrid.DataSource 属性。DataGrid.DataSource 属性接受任何实现 IList 接口的对象。考虑到这一点,让我们看一下 DirectoryInfo.GetDirectories()DirectoryInfo.GetFiles()Directory.FileSystemInfo() 返回的值。>。

DirectoryInfo.GetDirectories() 方法用于获取目录中所有子目录的集合。而 DirectoryInfo.GetFiles() 获取指定目录中所有文件的集合。另一方面,DirectoryInfo.GetFileSystemInfos() 获取文件夹中所有文件和目录的集合。由于这三个方法都返回文件、目录或两者兼有的集合,我们可以安全地假设,我们可以使用这些对象返回的结果集作为我们 DataGrid 的数据源。

下面的列表显示了如何使用 DirectoryInfo.FileSystemInfo() 列出文件夹的内容

private void Page_Load(object sender, System.EventArgs e)
{
    string folderToBrowse = @"c:\";
    
    DirectoryInfo DirInfo = 
        new DirectoryInfo(folderToBrowse);
    FileSystemGrid.DataSource = 
        DirInfo.GetFileSystemInfos();
    FileSystemGrid.DataBind();
}

请注意,您需要设置您的网格以接受 DirectoryInfo.GetFileSystemInfo 方法生成的值。示例文本如下

<asp:datagrid id="FileSystemGrid" runat="server" 
    BorderStyle="None" AutoGenerateColumns="False"
    Font-Size="XX-Small" Font-Names="Arial" 
    AllowSorting="True">
<Columns>
<asp:TemplateColumn HeaderText="Name">
<HeaderStyle Width="350px"></HeaderStyle>
<ItemTemplate>
<asp:HyperLink id=systemLink runat="server" NavigateUrl='' 
   Text='<%# DataBinder.Eval(Container, "DataItem.FullName") %>'>
</asp:HyperLink>
</ItemTemplate>
</asp:TemplateColumn>
<asp:BoundColumn DataField="CreationTime" 
    HeaderText="CreationTime">
<HeaderStyle Width="150px"></HeaderStyle>
</asp:BoundColumn>
<asp:BoundColumn DataField="LastWriteTime" 
    HeaderText="LastWriteTime">
<HeaderStyle Width="150px"></HeaderStyle>
</asp:BoundColumn>
</Columns>
</asp:datagrid>

第一个示例的结果如下所示

这很简单?对吧?

如果我们想添加一些用户交互怎么办?例如,单击选定的目录将允许用户浏览其下的文件和目录。要完成此任务,我们需要一个 LinkButton、我们的 DataTable 和我们的 DataGrid。但这次,我们将把文件夹表和文件表分开。这是必要的,因为我们希望有不同的交互。例如,单击文件夹将使我们能够浏览该文件夹下的子文件夹和文件,或者单击文件将使我们能够下载该文件。

这是解决此问题的 C# 示例

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.IO;
namespace KeithRull.FolderBrowserCS
{
    /// <summary>

    /// Summary description for theNewWayBrowser.

    /// </summary>

    public class theNewWayBrowser : System.Web.UI.Page
    {
        protected System.Web.UI.WebControls.DataGrid FileSystem;
        
        private void Page_Load(object sender, System.EventArgs e)
        {
            //read our query string, if its null, assign the default folder

            //to our variable else assign the query string value.

            string folderToBrowse = Request.QueryString["d"] == null ? 
                  FileBrowerProperty.IntialPath : Request.QueryString["d"];
            //read the folder 

            DirectoryInfo DirInfo = new DirectoryInfo(folderToBrowse);
            //create our datatable that would hold the list

            //of folders in the specified directory

            DataTable fileSystemFolderTable = new DataTable();
            //create our datatable that would hold the list

            //of files in the specified directory

            DataTable fileSystemFileTable = new DataTable();
            //create our datatable that would hold the list

            //of files and folders when we combine the two 

            //previously declared datatable

            DataTable fileSystemCombinedTable = new DataTable();
            
            //create the columns for our file datatable

            DataColumn dcFileType = new DataColumn("Type");
            DataColumn dcFileFullName = new DataColumn("FullName");
            DataColumn dcFileName = new DataColumn("Name");
            DataColumn dcFileCreationTime = new DataColumn("CreationTime");
            DataColumn dcFileLastWriteTime = new DataColumn("LastWriteTime");
            //create the columns for our folder datatable

            DataColumn dcFolderType = new DataColumn("Type");
            DataColumn dcFolderFullName = new DataColumn("FullName");
            DataColumn dcFolderName = new DataColumn("Name");
            DataColumn dcFolderCreationTime = new DataColumn("CreationTime");
            DataColumn dcFolderLastWriteTime = new DataColumn("LastWriteTime");
            //add the columns to our datatable

            fileSystemFolderTable.Columns.Add(dcFileType);
            fileSystemFolderTable.Columns.Add(dcFileName);
            fileSystemFolderTable.Columns.Add(dcFileFullName);
            fileSystemFolderTable.Columns.Add(dcFileCreationTime);
            fileSystemFolderTable.Columns.Add(dcFileLastWriteTime);
            fileSystemFileTable.Columns.Add(dcFolderType);
            fileSystemFileTable.Columns.Add(dcFolderName);
            fileSystemFileTable.Columns.Add(dcFolderFullName);
            fileSystemFileTable.Columns.Add(dcFolderCreationTime);
            fileSystemFileTable.Columns.Add(dcFolderLastWriteTime);
            //loop thru each directoryinfo object in the specified directory

            foreach(DirectoryInfo di in DirInfo.GetDirectories())
            {
            //create a new row in ould folder table

            DataRow fileSystemRow = fileSystemFolderTable.NewRow();
            
            //assign the values to our table members

            fileSystemRow["Type"] = "Directory";
            fileSystemRow["Name"] = di.Name;
            fileSystemRow["FullName"] = di.FullName;
            fileSystemRow["CreationTime"] = di.CreationTime;
            fileSystemRow["LastWriteTime"] = di.LastWriteTime;
            fileSystemFolderTable.Rows.Add(fileSystemRow);
            }
            //loop thru each fileinfo object in the specified directory

            foreach(FileInfo fi in DirInfo.GetFiles())
            {
            //create a new row in ould folder table

            DataRow fileSystemRow = fileSystemFileTable.NewRow();
            //assign the values to our table members

            fileSystemRow["Type"] = "File";
            fileSystemRow["Name"] = fi.Name;
            fileSystemRow["FullName"] = fi.FullName;
            fileSystemRow["CreationTime"] = fi.CreationTime;
            fileSystemRow["LastWriteTime"] = fi.LastWriteTime;
            fileSystemFileTable.Rows.Add(fileSystemRow);
            }
            
            //copy the folder table to our main datatable,

            //this is necessary so that the parent table would have the

            //schema of our child tables.

            fileSystemCombinedTable = fileSystemFolderTable.Copy();
            //loop thru each row of our file table

            foreach(DataRow drw in fileSystemFileTable.Rows)
            {
            //import the rows from our child table to the parent table

            fileSystemCombinedTable.ImportRow(drw);
            }
            
            //assign our file system parent table to our grid and bind it.

            FileSystem.DataSource = fileSystemCombinedTable;
            FileSystem.DataBind();
        }
        #region Web Form Designer generated code
        override protected void OnInit(EventArgs e)
        {
            //

            // CODEGEN: This call is required 

            // by the ASP.NET Web Form Designer.

            //

            InitializeComponent();
            base.OnInit(e);
        }
        
        /// <summary>

        /// Required method for Designer support - do not modify

        /// the contents of this method with the code editor.

        /// </summary>

        private void InitializeComponent()
        { 
            this.FileSystem.ItemCommand +=
                new DataGridCommandEventHandler(FileSystem_ItemCommand);
            this.Load += new System.EventHandler(this.Page_Load);
        }
        #endregion
        private void FileSystem_ItemCommand(object source, 
                                DataGridCommandEventArgs e)
        {
            //get the filepath from the specified 

            //command arguments for our linkbutton

            string filepath = e.CommandArgument.ToString();
            //get the file system type of the selected ite

            string fileSystemType = 
                FileSystem.Items[e.Item.ItemIndex].Cells[0].Text;
            //if its a directory, redirect to our page and passing

            //the new file path to our query string

            if(fileSystemType == "Directory")
            {
                Response.Redirect("theNewWayBrowser.aspx?d="+ 
                                   e.CommandArgument.ToString());
            }
            else
            { 
                //get the filename

                string filename = e.CommandName;
                
                //read the file to our stream

                Stream s = File.OpenRead(filepath);
                //create the bytes to be streamed

                Byte[] buffer = new Byte[s.Length];
                
                //build the buffer

                try { 
                    s.Read(buffer, 0, (Int32) s.Length); 
                }
                //close our stream

                finally { s.Close(); }
                //clear the response headers

                Response.ClearHeaders();
                //clear the content type

                Response.ClearContent();
                Response.ContentType = "application/octet-stream";
                //add our header

                Response.AddHeader("Content-Disposition", 
                     "attachment; filename=" + filename);
                //write the buffer to the http stream

                Response.BinaryWrite(buffer);
                //end response

                Response.End();
            }
        }
    }
}

下面显示了我们解决方案结果的截图

正如您所见,我们使用原生的 ASP.NET 对象,以与使用旧式 ASP 逻辑的第一个示例相同的结果完成了任务。

© . All rights reserved.