Search - Articles - Dev Forums - Favorites - Member Login  
DevASP.NET for ASP.NET, VB.NET, XML and C# (C-Sharp) Developers Wednesday, March 17, 2010

Dev Articles
Search Directory
ASP.NET
VB.Net
C-Sharp
SQL Server
 


Displaying the Creation and Last Modification Dates


The last two columns we want to fill are the Created and Last Modified columns. We're lucky here as there's almost nothing to do, since this information is returned by the CreationTime and LastWriteTime properties exposed by the DirectoryInfo and FileInfo classes.

 

Here's the code to add:

 

foreach (DirectoryInfo childDir in childDirs)

{

 

  // create the required cells and controls

  ...

  cellCreated = new TableCell();

  cellLastModified = new TableCell();

 

  ...    

  // set the created and last modified date

  cellCreated.Text = String.Format("{0:MM/dd/yy hh:mm tt}",

                                                  childDir.CreationTime);

  cellLastModified.Text = String.Format("{0:MM/dd/yy hh:mm tt}",

                                                 childDir.LastWriteTime);

 

  // add the cells to the new row

  ...

  rowItem.Cells.Add(cellCreated);

  rowItem.Cells.Add(cellLastModified);

   

  // add the new row to the table

  ...

}

 


foreach (FileInfo childFile in childFiles)

{

 

  // create the required cells

  ...

  cellCreated = new TableCell();

  cellLastModified = new TableCell();

 

  ...

  // set the created and last modified date

  cellCreated.Text = String.Format("{0:MM/dd/yy hh:mm tt}", +

                                                  childFile.CreationTime);

  cellLastModified.Text = String.Format("{0:MM/dd/yy hh:mm tt}", +

                                                 childFile.LastWriteTime);

 

  // add the cells to the new row

  ...

  rowItem.Cells.Add(cellCreated);

  rowItem.Cells.Add(cellLastModified);

 

  // add the new row to the table

  ...

}

 

We're finally done with the code for displaying the information about items! If you now recompile the assembly, and refresh the page in the browser, you should see something similar to the screenshot below:

 


 

Downloading Files

When you click on an item's link, the file manager opens a new browser window and redirects to that file. If the file is an image or HTML file then you'll see it loaded and displayed by the browser. Instead, if it is a file that the browser is not able to open, such as a ZIP file, it will ask you if you want to download it. However, there are other file types that the browser will neither load nor allow you to download. For example, with web.config or global.asax you'll get an error page containing the message "This type of page is not served". And other files, particularly ASPX files, are processed on the server – so you'll see the result of the processing, not the source code.

 

We need to find a way to download a file or view its content without resorting to FTP. We can solve this with streams.

Using streams, we can provide a file to the user 'as is' – without the interference of IIS.

We need a separate ASPX file, called download.aspx. This takes a filename as a parameter, and returns the content of that file – unprocessed by the web server. The ASPX file has no user interface – everything is done in the code-behind. Here's the code for download.aspx.cs Page_Load method:

 

private void Page_Load(object sender, System.EventArgs e)

{

  // retrieve the path of the file to download, and create

  // a FileInfo object to read its properties

  string path = Server.MapPath(Request.Params["File"]);

  System.IO.FileInfo file = new System.IO.FileInfo(path);

 

  // clear the current output content from the buffer

  Response.Clear();

  // add the header that specifies the default filename for the

  // Download/SaveAs dialog

  Response.AddHeader("Content-Disposition",

                                     "attachment; filename=" + file.Name);

  // add the header that specifies the file size, so that the browser

  // can show the download progress

  Response.AddHeader("Content-Length", file.Length.ToString());

  // specify that the response is a stream that cannot be read by the

  // client and must be downloaded

  Response.ContentType = "application/octet-stream";

  // send the file stream to the client

  Response.WriteFile(file.FullName);

  // stop the execution of this page

  Response.End();

}

 

We now need to add a download button to our BrowseFiles.aspx table. The button needs to point to Download.aspx with the appropriate parameter:


In the BrowseFiles.aspx file we need to add a new column to the FoldersAndFiles table:

 

<asp:Table ID="FoldersAndFiles" runat="server"

  CssClass="Grid_General" Width="100%">

  <asp:TableRow CssClass="Grid_Header">

    <asp:TableCell Width="36px" />

    <asp:TableCell Text="Index" />

    <asp:TableCell Width="25px" />

    <asp:TableCell Text="Attribs" Width="50px" />

    <asp:TableCell Text="Size" Width="80px" HorizontalAlign="Right" />

    <asp:TableCell Text="Created" Width="140px" />

    <asp:TableCell Text="Last Modified" Width="140px" />

  </asp:TableRow>

</asp:Table>

 

In FillFoldersAndFilesTable in the code-behind we have to create and add an empty cell for the first row, which points to the parent folder, and for all the child directories. We've seen how to do this previously, so we aren't going to repeat the code here. For the file rows we create a new cell and an image that links to Download.aspx, with the appropriate parameter:

 

// declare the required cells and controls

...

TableCell cellDownload;

HyperLink linkDownload;

...

 

// add an empty cell for all the rows that display a directory and to

// the row that points to the parent directory

...refer back to see how to add empty cells to the rows...

 

foreach (FileInfo childFile in childFiles)

{

  // create the required cells and controls

  ...

  cellDownload = new TableCell();

  linkDownload = new HyperLink();

 

  // set the other cells and controls

  ...

   

  // add the link to download the file

  linkDownload.Text = "<img src=\"./Images/Download.gif\" border=\"0\ +

      " height=\"16\" width=\"16\" Alt=\"Download\">";

  linkDownload.NavigateUrl = "Download.aspx?File=" + location;

  cellDownload.Controls.Add(linkDownload);

 

  // add the cells to the new row

  rowItem.Cells.Add(cellItemIcon);

  rowItem.Cells.Add(cellItemLink);

  rowItem.Cells.Add(cellDownload);

  rowItem.Cells.Add(cellAttributes);

  rowItem.Cells.Add(cellSize);

  rowItem.Cells.Add(cellCreated);

  rowItem.Cells.Add(cellLastModified);


   

  // add the new row to the table

  rowItem.ApplyStyle(styleFileRow);

  FoldersAndFiles.Rows.Add(rowItem);

}

 

Now when we click the download icon, the source file will be downloaded – regardless of the file type.

Uploading Files

In addition to downloading files, we also want to upload files. Although we would certainly use FTP if we had to upload lots of files, this tool can be quite handy if you just need to upload a couple of files.

 

To select the file to upload we can use the standard HTML input control of type file. This comprises a textbox and a Browse button, which when pressed opens the Choose File dialog that allows the user to select a file. This control can be used and accessed in ASP.NET by adding the
runat="server" attribute.

In order to accept the submitted file, the form must be declared with the attribute enctype="multipart/form-data".

Let's update our BrowseFiles.aspx page by adding this control and a button to submit the file:

 

<form id="BrowseFiles" method="post" runat="server"

    enctype="multipart/form-data">

<!-- other controls as above here -->

...

<asp:Table ID="FoldersAndFiles" runat="server" CssClass="Grid_General"

    Width="100%">

  <asp:TableRow CssClass="Grid_Header">

    <asp:TableCell Width="36px" />

    <asp:TableCell Text="Index" />

    <asp:TableCell Width="25px" />

    <asp:TableCell Text="Attribs" Width="50px" />

    <asp:TableCell Text="Size" Width="80px" HorizontalAlign="Right" />

    <asp:TableCell Text="Created" Width="140px" />

    <asp:TableCell Text="Last Modified" Width="140px" />

  </asp:TableRow>

</asp:Table>

<br>

<asp:Table runat="server">

  <asp:TableRow>

    <asp:TableCell Width="80px" Font-Bold="True" Text="Upload file:" />

    <asp:TableCell>

      <input type="file" ID="UploadedFile" runat="server" size="35">

    </asp:TableCell>

    <asp:TableCell>

      <asp:Button ID="Upload" runat="server" Text="Upload"

          CssClass="Button" OnClick="Upload_Click" />

    </asp:TableCell>

  </asp:TableRow>

</asp:Table>

<!-- other controls as above here -->

...

</form>


If we now save the file, VS.NET should add the following declaration to the code-behind:

 

public class BrowseFiles : System.Web.UI.Page

{

  protected System.Web.UI.HtmlControls.HtmlInputFile UploadedFile;

 

  // other controls below

  ...

 

The following code is for the Upload_Click event handler, whose function is to upload the selected file to the current directory, but only if a file has been selected:

 

protected void Upload_Click(object sender, EventArgs e)

{

 

  // proceed only if a file has been specified

  if (UploadedFile.PostedFile != null &&

    UploadedFile.PostedFile.FileName.Length > 0 )

  {

    string destDir = Server.MapPath(folderPath);

 

    try

    {

 

      // save to the current directory

      string fileName = Path.GetFileName(UploadedFile.PostedFile.FileName);

      UploadedFile.PostedFile.SaveAs(Path.Combine(destDir, fileName));

 

      // refresh the page

      Response.Redirect("BrowseFiles.aspx?Folder=" + folderPath);

    }

    catch (Exception exc)

    {

      StatusMessage.Text = exc.Message;

      StatusMessage.Visible = true;

    }

  }

}

 

The code is straightforward, but you should note one point: after the file is uploaded to the server, we refresh the table by reloading the entire page. This is necessary because in Page_Load the table was filled, so if we called FillFoldersAndFilesTable again here we would get all the rows twice. Since the redirection is done on the server before any HTML code is sent to the client browser, this does not cause much overhead.

 

Also note that the code that uploads the file is protected by a try...catch block. In case an exception occurs, for example because the current user does not have permission to write on this directory, an error message is shown in the StatusMessage label.

Note that by default the maximum size of the uploaded file is 4MB. If you try to upload a bigger size you'll get an error page. You may want to increase this value, for example because you have ZIP, AVI, or MP3 files bigger than 4MB. To do so, set the maxRequestLength attribute of the <httpRuntime> setting in the ThePhile's web.config file. The size is specified in KB, so <httpRuntime maxRequestLength="8192" /> sets the maximum file size to 8MB.


It's time to recompile everything and jump to the browser to test the updated file manager. In the screenshot below you can see both the new icons added to the files to download or open them, as well as the file input control and the Choose file dialog:

 

 


DevASP.Net - Disclaimer - Privacy
© 2002-2010 DevASP.net