15.3.1 Problem You want a user to be able to upload a file to the web server for immediate processing, without having to first store the file. 15.3.2 Solution Implement the solution described in Recipe 15.2 but instead of writing the file to the filesystem, use the input stream containing the uploaded file to process the data. For the .aspx file, follow the steps for implementing the .aspx file in Recipe 15.2 and then, if you like, add a control that will show the results of the processing ”for example, a DataGrid control to display the contents of an uploaded XML file. In the code-behind file for the page, use the .NET language of your choice to: -
Verify, in the Upload button click event handler, that the file has been uploaded ”that is, that the length of the filename and the file contents are both greater than 0 ”and (if appropriate) that it is a valid XML file. -
Load the updated data and, if you elected to include a control for showing the contents of the uploaded file, bind the uploaded data to the control ”for example, a DataGrid control. Example 15-8 through Example 15-10 show the .aspx file and VB and C# code-behind files for an application we've written to illustrate this solution. The initial output is identical to Recipe 15.2s example output and is shown in Figure 15-3. 15.3.3 Discussion This recipe demonstrates the concept of uploading files and processing them without having to store them to the local filesystem, as you might do with the contents of an XML file for example. This eliminates the problems of files being uploaded with the same names , inadvertently filling the hard drive, and the security aspects of allowing the ASPNET write privileges on the local filesystem. The example that we've written to illustrate this solution is similar to that described in Recipe 15.2, except that instead of saving the file contents to the filesystem, we process it immediately by loading the uploaded data into a DataSet and then binding the DataSet to a DataGrid . What's more, our example uses the basic .aspx file described in Recipe 15.2 with a few changes to support using the page for uploading an XML file and displaying its contents. In the Page_Load method of the code-behind, the table containing the upload controls is made visible and the DataGrid invisible. (We'll switch the visibility of the two at a later stage to display the contents of the processed file.) When the user clicks the Upload button, the btnUpload_ServerClick method is executed. The code for making sure a file was uploaded is identical to our example code in Recipe 15.2. An additional check has been added in this example to ensure the uploaded file is an XML file because this example is expecting XML data. Because the same page is used to display the contents of the uploaded file, the table containing the upload controls now needs to be made invisible and the DataGrid used to display the contents of the uploaded file made visible. Next, we use PostedFile.InputStream to load the data into the DataSet . In our example, the XML file shown in Example 15-7 is being uploaded and because of its formatting can be read directly into the DataSet . With other types of data, you may need to do other processing. In addition, production code should validate the content type of the posted file as well as the contents of the file itself to ensure the uploaded file is valid. Example 15-7. XML file uploaded <Root> <Book> <BookID>1</BookID> <Title>Access Cookbook</Title> <ISBN>0-596-00084-7</ISBN> <Publisher>O'Reilly</Publisher> </Book> <Book> <BookID>2</BookID> <Title>Perl Cookbook</Title> <ISBN>1-565-92243-3</ISBN> <Publisher>O'Reilly</Publisher> </Book> <Book> <BookID>3</BookID> <Title>Java Cookbook</Title> <ISBN>0-596-00170-3</ISBN> <Publisher>O'Reilly</Publisher> </Book> <Book> <BookID>4</BookID> <Title>JavaScript Application Cookbook</Title> <ISBN>1-565-92577-7</ISBN> <Publisher>O'Reilly</Publisher> </Book> <Book> <BookID>5</BookID> <Title>VB .Net Language in a Nutshell</Title> <ISBN>0-596-00092-8</ISBN> <Publisher>O'Reilly</Publisher> </Book> <Book> <BookID>6</BookID> <Title>Programming Visual Basic .Net</Title> <ISBN>0-596-00093-6</ISBN> <Publisher>O'Reilly</Publisher> </Book> <Book> <BookID>7</BookID> <Title>Programming C#</Title> <ISBN>0-596-00117-7</ISBN> <Publisher>O'Reilly</Publisher> </Book> <Book> <BookID>8</BookID> <Title>.Net Framework Essentials</Title> <ISBN>0-596-00165-7</ISBN> <Publisher>O'Reilly</Publisher> </Book> <Book> <BookID>9</BookID> <Title>COM and .Net Component Services</Title> <ISBN>0-596-00103-7</ISBN> <Publisher>O'Reilly</Publisher> </Book> </Root> The last step in our example is to bind the DataGrid on the form to the DataSet containing the uploaded XML file. Figure 15-4 shows the output for the uploaded and processed file. For more information on data binding, refer to the recipes in Chapter 1. Figure 15-4. Uploaded and processed file output 15.3.4 See Also Chapter 2 for validation controls; HtmlInputFile class documentation in the MSDN library for more information on file uploads Example 15-8. Upload file and process (.aspx) <%@ Page Language="vb" AutoEventWireup="false" Codebehind="CH15FileUploadAndProcessVB.aspx.vb" Inherits="ASPNetCookbook.VBExamples.CH15FileUploadAndProcessVB" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <title>File Upload And Process</title> <link rel="stylesheet" href="css/ASPNetCookbook.css"> </head> <body leftmargin="0" marginheight="0" marginwidth="0" topmargin="0"> <form id="frmUpload" method="post" runat="server" enctype="multipart/form-data"> <table width="100%" cellpadding="0" cellspacing="0" border="0"> <tr> <td align="center"> <img src="images/ASPNETCookbookHeading_blue.gif"> </td> </tr> <tr> <td class="dividerLine"> <img src="images/spacer.gif" height="6" border="0"></td> </tr> </table> <table width="90%" align="center" border="0"> <tr> <td align="center"> </td> </tr> <tr> <td align="center" class="PageHeading"> File Upload And Process (VB) </td> </tr> <tr> <td><img src="images/spacer.gif" height="10" border="0"></td> </tr> <tr> <td align="center"> <!-- The following table is displayed when the user is uploading a file --> <table id="tabUpload" runat="server" width="60%" border="0"> <tr> <td align="center"> <input id="txtUpload" runat="server" type="file" > </td> </tr> <tr> <td align="center"> <br /> <input id="btnUpload" runat="server" type="button" value="Upload" name="btnUpload"> </td> </tr> </table> <!-- The following datagrid is displayed to show the data from the uploaded file --> <asp:DataGrid id="dgBooks" runat="server" BorderColor="000080" BorderWidth="2px" AutoGenerateColumns="False" width="100%"> <HeaderStyle HorizontalAlign="Center" ForeColor="#FFFFFF" BackColor="#000080" Font-Bold=true CssClass="TableHeader" /> <ItemStyle BackColor="#FFFFE0" cssClass="TableCellNormal" /> <AlternatingItemStyle BackColor="#FFFFFF" cssClass="TableCellAlternating" /> <Columns> <asp:BoundColumn HeaderText="Title" DataField="Title" /> <asp:BoundColumn HeaderText="ISBN" DataField="ISBN" ItemStyle-HorizontalAlign="Center" /> <asp:BoundColumn HeaderText="Publisher" DataField="Publisher" ItemStyle-HorizontalAlign="Center" /> </Columns> </asp:DataGrid> </td> </tr> </table> </form> </body> </html> Example 15-9. Upload file and process code-behind (.vb) Option Explicit On Option Strict On '----------------------------------------------------------------------------- ' ' Module Name: CH15FileUploadAndProcessVB.aspx.vb ' ' Description: This module provides the code behind for the ' CH15FileUploadAndProcessVB.aspx page ' '***************************************************************************** Imports Microsoft.VisualBasic Imports System Imports System.Data Imports System.IO Imports System.Web.UI Namespace ASPNetCookbook.VBExamples Public Class CH15FileUploadAndProcessVB Inherits System.Web.UI.Page 'controls on the form Protected tabUpload As System.Web.UI.HtmlControls.HtmlTable Protected txtUpload As System.Web.UI.HtmlControls.HtmlInputFile Protected WithEvents btnUpload As HtmlControls.HtmlInputButton Protected dgBooks As System.Web.UI.WebControls.DataGrid '************************************************************************* ' ' ROUTINE: Page_Load ' ' DESCRIPTION: This routine provides the event handler for the page load ' event. It is responsible for initializing the controls ' on the page. '------------------------------------------------------------------------- Private Sub Page_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load If (Not Page.IsPostBack) Then 'make the table containing the upload controls visible and 'the datagrid with the uploaded data invisible tabUpload.Visible = True dgBooks.Visible = False End If End Sub 'Page_Load '*************************************************************************** ' ' ROUTINE: btnUpload_ServerClick ' ' DESCRIPTION: This routine provides the event handler for the upload ' button click event. It is responsible processing the ' file and displaying the contents. '--------------------------------------------------------------------------- Private Sub btnUpload_ServerClick(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles btnUpload.ServerClick Dim ds As DataSet Dim filename As String 'make sure file was specified, was found, and is an xml file filename = txtUpload.PostedFile.FileName.Trim If ((filename.Length > 0) And _ (txtUpload.PostedFile.ContentLength > 0) And _ (txtUpload.PostedFile.ContentType.Equals("text/xml"))) Then 'make the table containing the upload controls invisible and 'the datagrid with the uploaded data visible tabUpload.Visible = False dgBooks.Visible = True 'load uploaded data into the dataset ds = New DataSet ds.ReadXml(txtUpload.PostedFile.InputStream) 'bind the data to the datagrid on the form dgBooks.DataSource = ds dgBooks.DataBind( ) Else 'production code should notify user of upload error here End If End Sub 'btnUpload_ServerClick End Class 'CH15FileUploadAndProcessVB End Namespace Example 15-10. Upload file and process code-behind (.cs) //---------------------------------------------------------------------------- // // Module Name: CH15FileUploadAndProcessCS.aspx.cs // // Description: This module provides the code behind for the // CH15FileUploadAndProcessCS.aspx page // //**************************************************************************** using System; using System.Data; using System.IO; namespace ASPNetCookbook.CSExamples { public class CH15FileUploadAndProcessCS : System.Web.UI.Page { // controls on the form protected System.Web.UI.HtmlControls.HtmlTable tabUpload; protected System.Web.UI.HtmlControls.HtmlInputFile txtUpload; protected System.Web.UI.HtmlControls.HtmlInputButton btnUpload; protected System.Web.UI.WebControls.DataGrid dgBooks; //************************************************************************ // // ROUTINE: Page_Load // // DESCRIPTION: This routine provides the event handler for the page // load event. It is responsible for initializing the // controls on the page. //------------------------------------------------------------------------ private void Page_Load(object sender, System.EventArgs e) { // wire the upload button event handler this.btnUpload.ServerClick += new EventHandler(this.btnUpload_ServerClick); if (!Page.IsPostBack) { // make the table containing the upload controls visible and // the datagrid with the uploaded data invisible tabUpload.Visible = true; dgBooks.Visible = false; } } // Page_Load //************************************************************************ // // ROUTINE: btnUpload_ServerClick // // DESCRIPTION: This routine provides the event handler for the upload // button click event. It is responsible processing the // file and displaying the contents. //------------------------------------------------------------------------ private void btnUpload_ServerClick(object sender, System.EventArgs e) { string filename = null; DataSet ds = null; // make sure file was specified, was found, and is an xml file filename = txtUpload.PostedFile.FileName.Trim( ); if ((filename.Length > 0) && (txtUpload.PostedFile.ContentLength > 0) && (txtUpload.PostedFile.ContentType.Equals("text/xml"))) { // make the table containing the upload controls invisible and // the datagrid with the uploaded data visible tabUpload.Visible = false; dgBooks.Visible = true; //load uploaded data into the dataset ds = new DataSet( ); ds.ReadXml(txtUpload.PostedFile.InputStream); // bind the data to the datagrid on the form dgBooks.DataSource = ds; dgBooks.DataBind( ); } else { // production code should notify user of upload error here } } // btnUpload_ServerClick } // CH15FileUploadAndProcessCS } |