Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

A Custom File Upload Using a Web Control and Integrated Validation

3.69/5 (7 votes)
30 Oct 2006CPOL3 min read 3   686  
This is a Web Control which is a custom file upload. It will accept only a specified range of file formats, and also integrates with the target page's validation.

Introduction

I have wrote this article to demonstrate custom validation with web controls.

As I only wanted the Custom Validator to fire when a button on an .aspx page had been clicked, all I am going to show in this article is how to create a simple File Upload control, which:

  • Only accepts .gif, .jpg, .png, .bmp.
  • Allow the user to state whether the image is required or not.

Pages Involved

Here is the page (with code file) which we will implement the control on:

  • Default.aspx
  • Default.aspx.cs

Here are the Web Control page names:

  • CustomControl.ascx
  • CustomControl.ascx.cs

Tasks for the Web Control (CustomControl.ascx)

For the web control, we need to do the following:

  • Add a File Upload
  • Add a Custom Validator
  • Assign something to the Custom Validator's ServerValidate event

Here is the code:

ASP.NET
<%@ Control Language="C#" AutoEventWireup="true" 
  CodeFile="CustomControl.ascx.cs" Inherits="WebUserControl" %>
<asp:FileUpload ID="FilUpl" runat="server" />
<br />
<asp:CustomValidator ID="ErrorMsg" runat="server" 
  ErrorMessage="CustomValidator" 
  OnServerValidate="ErrorMsg_ServerValidate">
</asp:CustomValidator><br />

Tasks for the Web Control Code File (CustomControl.ascx.cs)

For the code file for the Web Control, we need to:

  • define all the private variables.
  • define all the gets/sets which we will use to set the tag parameters and retrieve others.
  • define the ServerValidate function which we assigned to the custom validator.
  • define a function to get the file extension of the file which is attempting to upload.

Here is the code:

C#
public partial class CustomControl : System.Web.UI.UserControl
{
    //Has the user browsed for a file?
    private bool pGotFile;
    //The file extension of the Posted File
    private string pFileExt;
    //The File itself
    private HttpPostedFile pFilePost;
    //Is the user required to upload an image?
    private bool pRequired;
    //The validation group that the Custom Validator belongs to on the page
    private string pVgroup;
    //Extensions you allow to be uploaded
    private string[] pFileTypeRange;
    //Boolean indicator to check if file extension is allowed
    private bool Ind = false;

    /*
     * Get and Sets for the above private variables.
     * */
    public bool GotFile
    {
        get { return pGotFile; }
    }
    public string FileExt
    {
        get { return pFileExt; }
    }
    public HttpPostedFile FilePost
    {
        get { return pFilePost; }
    }
    public bool Required
    {
        set { pRequired = value; }
    }
    public string Vgroup
    {
        set { pVgroup = value; }
    }
    public string FileTypeRange
    {
        set { pFileTypeRange = value.ToString().Split(','); }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        //here we assign the validation group to the Custom Validator, 
        //which I have inefficiently named ErrorMsg
        ErrorMsg.ValidationGroup = pVgroup;
    }

    protected void ErrorMsg_ServerValidate(object source, 
                   ServerValidateEventArgs args)
    {
        if (FilUpl.HasFile)
        {
            pGotFile = true;
            pFileExt = GetExtension(FilUpl.PostedFile.FileName);
            pFilePost = FilUpl.PostedFile;

            foreach (string str in pFileTypeRange)
            {
                if (str == pFileExt)
                {
                    Ind = true;
                }
            }

            if (!Ind)
            {
                args.IsValid = false;
                ErrorMsg.Text = "The file format you " + 
                                "specified is not supported";
                //Stop the function
                return;
            }
        }
        else
        {
            //So if we get here the user has not browsed for a file
            pGotFile = false;
            //If you have stated that the user has to browse for a file.
            //then we must stop now and inform the user of such.
            if (pRequired)
            {
                args.IsValid = false;
                ErrorMsg.Text = "You must upload something";
            }
        }
    }
    /// <summary>
    /// This returns the file extension. It does not contain the preceding full stop
    /// so it would return jpg and NOT .jpg . Please adjust your coding accordingly.
    /// </summary>
    /// <param name="FileName">string</param>
    /// <returns>string: the file extension e.g. jpg</returns>
    private string GetExtension(string FileName)
    {
        string[] split = FileName.Split('.');
        string Extension = split[split.Length - 1];
        return Extension;
    }
}

Tasks for the Test Page (Default.aspx)

  • Add the tag line at the very top of your page which registers the custom tag which we will use:
  • ASP.NET
    <%@ Register TagPrefix="CC1" TagName="IUpload" Src="CustomControl.ascx" %>
  • Add the tag itself and also a button underneath which we will use to trigger the file upload.
  • ASP.NET
    <CC1:IUpload ID="MyUpload1" runat="server" 
       Required="false" Vgroup="Val1" FileTypeRange="jpg,gif,png,bmp" />
     
    <asp:Button ID="Button1" runat="server" Text="Upload Image" 
      CausesValidation="true" ValidationGroup="Val1" OnClick="Button1_Click"/>

Tasks for the Test Page's Code File (Default.aspx.cs)

  • Add the event for the button.
  • Inside this event, check to see if the page is valid. Check to see if there is a file, and if so, upload it.

Here is the code:

C#
public partial class _Default : System.Web.UI.Page 
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }
    protected void Button1_Click(object sender, EventArgs e)
    {
        //First We Check if the page is valid or if we need to flag up an error message
        if (Page.IsValid)
        {
            //Second we need to check if the user has browsed for a file
            if (MyUpload1.GotFile)
            {
                //We can safely upload the file here because it has passed all validation.
                //Remeber to add the fullstop before
                //the FileExt variable as it comes without.
                MyUpload1.FilePost.SaveAs(Server.MapPath("images/MyFile." + 
                                                         MyUpload1.FileExt));
            }
        }
    }
}

Please Note

I have developed this using ASP.NET version 2.0, and also using Visual Web Developer Express.

Updates

Update with Effect from 11 August 2006

I am going to insert something extra to this. Let's say that for the file type range, you specify jpg,png,gif,bmp, then you might also want to check that the width of the image meets a certain minimum requirement that you set in the tag. It will check the size without having to save it to disk, by using InputStream.

Here is how I achieve the check without saving the file to disk first:

C#
System.Drawing.Image CheckSize = 
       System.Drawing.Image.FromStream(FilUpl.PostedFile.InputStream);
if (CheckSize.PhysicalDimension.Width < minWidth)
{
    //Conditional actions here
}

So here is the code again, but this time with the inclusion of the image size check. If it does not meet the required minimum width, it will output this: "Your image does not meet the required minimum size requirements which are" + MinWidth +"px" etc...

C#
using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

public partial class CustomControl : System.Web.UI.UserControl
{
    //Has the user browsed for a file?
    private bool pGotFile;
    //The file extension of the Posted File
    private string pFileExt;
    //The File itself
    private HttpPostedFile pFilePost;
    //Is the user required to upload an image?
    private bool pRequired;
    //The validation group that the Custom Validator belongs to on the page
    private string pVgroup;
    //Extensions you allow to be uploaded
    private string[] pFileTypeRange;
    //Boolean indicator to check if file extension is allowed
    private bool Ind = false;
    //The Image Minimum Width
    private int minWidth = 0;


    /*
     * Get and Sets for the above private variables.
     * */
    public bool GotFile
    {
        get { return pGotFile; }
    }
    public string FileExt
    {
        get { return pFileExt; }
    }
    public HttpPostedFile FilePost
    {
        get { return pFilePost; }
    }
    public bool Required
    {
        set { pRequired = value; }
    }
    public string Vgroup
    {
        set { pVgroup = value; }
    }
    public string FileTypeRange
    {
        set { pFileTypeRange = value.ToString().Split(','); }
    }
    public int MinWidth
    {
        set { minWidth = value; }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        //here we assign the validation group to the Custom Validator, 
        //which I have inefficiently named ErrorMsg
        ErrorMsg.ValidationGroup = pVgroup;
    }

    protected void ErrorMsg_ServerValidate(object source, 
                   ServerValidateEventArgs args)
    {
        if (FilUpl.HasFile)
        {
            pGotFile = true;
            pFileExt = GetExtension(FilUpl.PostedFile.FileName);
            pFilePost = FilUpl.PostedFile;

            foreach (string str in pFileTypeRange)
            {
                if (str == pFileExt)
                {
                    Ind = true;
                }
            }

            if (!Ind)
            {
                args.IsValid = false;
                ErrorMsg.Text = "The file format you specified is not supported";
                //Stop the function
                return;
            }

            if (minWidth > 0)
            {
                //If you get here then you have set
                //the MinWidth because you are expecting an image,
                //and due to validation once at this stage in the code,
                //we know that the user has uploaded some sort of image type
                System.Drawing.Image CheckSize = 
                  System.Drawing.Image.FromStream(FilUpl.PostedFile.InputStream);
                if (CheckSize.PhysicalDimension.Width < minWidth)
                {
                    args.IsValid = false;
                    ErrorMsg.Text = "Your image does not meet the minimum width " + 
                      "requirements which are " + minWidth.ToString() +"px";
                    //Stop the function
                    return;
                }
            }
        }
        else
        {
            //So if we get here the user has not browsed for a file
            pGotFile = false;
            //If you have stated that the user has to browse for a file.
            //then we must stop now and inform the user of such.
            if (pRequired)
            {
                args.IsValid = false;
                ErrorMsg.Text = "You must upload something";
            }
        }
    }
    /// <SUMMARY>
    /// This returns the file extension. It does not contain the preceding full stop
    /// so it would return jpg and NOT .jpg . Please adjust your coding accordingly.
    /// </SUMMARY>
    /// <PARAM name="FileName">string</PARAM>
    /// <RETURNS>string: the file extension e.g. jpg</RETURNS>
    private string GetExtension(string FileName)
    {
        string[] split = FileName.Split('.');
        string Extension = split[split.Length - 1];
        return Extension;
    }
}

Finally the Updated Tag

Inline with my updated code, here is how I would implement it in the Custom Tag.

Register the tag first, I am using a different tag prefix this time:

ASP.NET
<%@ Register TagPrefix="ARDesigns" TagName="IUpload" Src="CustomControl.ascx" %>

And then the tag itself:

ASP.NET
<ARDesigns:IUpload ID="MyUpload1" runat="server" 
  Vgroup="Val1" FileTypeRange="jpg,gif,png,bmp" MinWidth="400" />

Update with Effect from 3 September 2006

Basically, I needed to put this in as I tripped over myself yesterday. Simple, but slipped my mind. People can have files with upper case file extensions, so we need to put it into lowercase to make the comparison, i.e.:

C#
pFileExt = GetExtension(FilUpl.PostedFile.FileName).ToLower();

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)