使用 Web 控件和集成验证的自定义文件上传






3.69/5 (7投票s)
这是一个 Web 控件,它是一个自定义的文件上传控件。它将只接受指定范围的文件格式,并与目标页面的验证集成。
引言
我写这篇文章是为了演示 Web 控件的自定义验证。
因为我只希望当 .aspx 页面上的按钮被点击时才触发自定义验证器,所以我将在本文中展示如何创建一个简单的文件上传控件,该控件:
- 仅接受 .gif、.jpg、.png、.bmp。
- 允许用户声明图像是否为必需的。
涉及的页面
这是我们将在其上实现控件的页面(带有代码文件)
- Default.aspx
- Default.aspx.cs
以下是 Web 控件页面名称
- CustomControl.ascx
- CustomControl.ascx.cs
Web 控件的任务 (CustomControl.ascx)
对于 Web 控件,我们需要做以下事情:
- 添加一个文件上传控件
- 添加一个自定义验证器
- 将某些内容分配给自定义验证器的 ServerValidate事件
这是代码
<%@ 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 />
Web 控件代码文件的任务 (CustomControl.ascx.cs)
对于 Web 控件的代码文件,我们需要:
- 定义所有私有变量。
- 定义我们将用于设置标记参数和检索其他参数的所有 get/set 方法。
- 定义我们分配给自定义验证器的 ServerValidate函数。
- 定义一个函数来获取尝试上传的文件的文件扩展名。
这是代码
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;
    }
}
测试页面的任务 (Default.aspx)
- 在页面最顶部添加标记行,该标记行注册我们将使用的自定义标记
<%@ Register TagPrefix="CC1" TagName="IUpload" Src="CustomControl.ascx" %>
<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"/>
测试页面的代码文件的任务 (Default.aspx.cs)
- 为按钮添加事件。
- 在此事件中,检查页面是否有效。检查是否存在文件,如果存在,则上传它。
这是代码
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));
            }
        }
    }
}
请注意
我使用 ASP.NET 2.0 版和 Visual Web Developer Express 开发了此程序。
更新
2006 年 8 月 11 日起生效的更新
我将在此处插入一些额外的内容。假设对于文件类型范围,您指定 jpg,png,gif,bmp,那么您可能还需要检查图像的宽度是否满足您在标记中设置的某个最小要求。它将通过使用 InputStream 检查大小,而无需将其保存到磁盘。
以下是我如何在不首先将文件保存到磁盘的情况下实现检查的方法
System.Drawing.Image CheckSize = 
       System.Drawing.Image.FromStream(FilUpl.PostedFile.InputStream);
if (CheckSize.PhysicalDimension.Width < minWidth)
{
    //Conditional actions here
}
这是再次的代码,但这次包含图像大小检查。如果它不符合所需的最小宽度,它将输出此内容:“您的图像不符合所需的最小大小要求,即”+ MinWidth +"px" 等...
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;
    }
}
最后更新的标签
与我的更新代码一致,以下是我如何在自定义标签中实现它。
首先注册标签,这次我使用了不同的标签前缀
<%@ Register TagPrefix="ARDesigns" TagName="IUpload" Src="CustomControl.ascx" %>
然后是标签本身
<ARDesigns:IUpload ID="MyUpload1" runat="server" 
  Vgroup="Val1" FileTypeRange="jpg,gif,png,bmp" MinWidth="400" />
2006 年 9 月 3 日起生效的更新
基本上,我需要将此内容放入,因为我昨天绊倒了自己。很简单,但从我的脑海中溜走了。人们可以拥有带有大写文件扩展名的文件,因此我们需要将其转换为小写以进行比较,即。
pFileExt = GetExtension(FilUpl.PostedFile.FileName).ToLower();


