Click here to download the source code for this lesson.
In this lesson I am going to show you how to use the ASP.NET FileUpload and CustomValidator controls. We will walk through an example together. I setup a web form named FileUploadPage.aspx that allows a user to upload a .jpg picture file to the server. The example code that I have performs some basic validation on the uploaded file such as ensuring that the size of the file falls within a certain range. If the validation succeeds, the code saves the file to a folder called “uploads”. Let me first describe the two server controls a little bit.
The ASP.NET FileUpload control can be used when you want the user to upload a file and then save the file on the server or in a database. You have be careful when you use this server control because you are giving the user the ability to temporarily perform operations on the web server which could be hazardous to your server’s health. An example of this is if a malicious user repeatedly submits large files to clog your server’s resources (hard drive space, etc.). *A couple of tips to keep your applications more secure are to restrict the size of the files that you allow the user to upload and do NOT allow the user to name the target file that is saved on your web server (i.e. your application should create the filename). I will show you how to implement these two tips in this lesson. When you use the FileUpload control you have the option to either save the uploaded file to the server’s hard disk, or you can access the file in memory and put it somewhere else (e.g. in a database table). *Putting large files in a database table is something that I would avoid because it can turn your database into a huge and difficult to manage entity.
The ASP.NET CustomValidator control allows you to create server side validation methods and associate them with particular controls that are in your web form. This is contrast to the RequiredFieldValidator, RangeValidator and RegularExpressionValidator controls that I covered in previous blog entries. With those other validation controls, you don’t really have to write any code, but with the CustomValidator you can create your own validation rules in C# code. In this lesson I am going to use the CustomValidator to make sure that an uploaded file size doesn’t exceed a predefined maximum size. The CustomValidator control does have a couple of Properties that are similar to the other validation controls. Those are the ControlToValidate and the ErrorMessage properties. Click here to learn more about the other validation controls and properties mentioned here. Look for the articles with the title of ASP.NET validation controls.
Alright, now let me take you step by step through the lesson. First I dragged a FileUpload control onto my web form FileUploadPage.aspx. The FileUpload control is in the Standard group of Toolbox controls. After you drag it onto a web form the FileUpload looks like a TextBox with a Browse button right next to it. The FileUpload server control is actually rendered as an HTML input type=”file” tag in the browser. The ID of my control is “FileUpload1″.
<asp:FileUpload ID="FileUpload1" runat="server" />
Next I added an Upload button that is responsible for posting the web form back to the web server. Then I dragged a couple of CustomValidator controls underneath the button. The CustomValidator controls are in the Validation group in the Toolbox. The first CustomValidator control that I put in my form is responsible for making sure that the uploaded file is at least 1K in size. I set its ErrorMessage property to “File must be at least 1K”. If the validation fails for this control, that message will be displayed to the user on the web page. Next I set the CustomValidator OnServerValidate property to “validateMinimumFileSize”. The OnServerValidate specifies the name of a server side method that will execute the code for the CustomValidator control. In my example, I have a method in my code behind class file named validateMinimumFileSize. When my web form executes and a post back occurs, ASP.NET will automatically call my validateMinimumFileSize method. This only happens during post backs (e.g. when a button is pressed).
<asp:CustomValidator ID="CustomValidator1" runat="server" ControlToValidate="FileUpload1" ErrorMessage="File must be at least 1K" OnServerValidate="validateMinimumFileSize"></asp:CustomValidator>
I then created the validateMinimumFileSize method in my FileUploadPage code behind class file. Since the method is going to be called automatically by the control and ASP.NET, the method has to follow a specific signature (i.e. you have to put a couple of standard method input arguments). I will tell you a little bit more about the arguments later. Let’s take a look at what my example method looks like.
protected void validateMinimumFileSize(object source, ServerValidateEventArgs args) { //Get the information about the file that was uploaded. HttpPostedFile postedfile = FileUpload1.PostedFile; //If the file was less than the minimum size //of 1K, reject it. if (postedfile.ContentLength < 1024) { args.IsValid = false; mPassedValidation = false; } else args.IsValid = true; }
On the first line of my method, I am getting an HttpPostedFile object from the FileUpload control. That object contains the file that was uploaded to the server and has a ContentLength property that I can access to determine the size of the file. I check that value and if it is less than 1K, I set the IsValid property to false. The args input argument contains the IsValid property so that your method can communicate with ASP.NET to let it know whether or not the validation failed. If you set it equal to false, ASP.NET will assume that the validation failed and display the ErrorMessage on the web page. Setting it to true, passes the validation.
I repeated pretty much the same steps for the second CustomValidator control that checks to make sure that the file size doesn’t exceed a certain limit. In that case I am calling a method named validateMaximumFileSize. That method looks very similar to the other validation method above. If I wanted to perform additional validation logic in this web page, I could drag additional CustomValidator controls and create more server side methods to perform validation business logic.
The advantage of using CustomValidator in this fashion is that it separates the validation logic from your other processing. Also, it comes in handy because you can create as many server side rules as you want and ASP.NET will automatically call all of them for you. This is a big benefit of event driven programming in C# with ASP.NET. Now let’s look at the actual processing of the file during the upload.
I created a button click event handler method for the Upload button named btnUpload_Click. Here it is.
protected void btnUpload_Click(object sender, EventArgs e) { //If the file passed all the validation rules, only //then do we save it to the hard drive. if (mPassedValidation) { string serverfilename = System.Guid.NewGuid().ToString() + ".jpg"; FileUpload1.SaveAs(Server.MapPath("") + "\\Uploads\\" + serverfilename); txtResults.Text = "File successfully uploaded at " + DateTime.Now.ToString() + "\r\n"; } else txtResults.Text = ""; }
In this method I am creating a unique file name for the uploaded file by using a .NET Guid object. This will create a file name that will look something like “020261de-0627-43a2-b4f4-a0911488e7f5.jpg”. This is to ensure that no two users can have the same file name and it also eliminates the security risk of allowing the user to name their file on the server. To save the file to the hard disk on the web server I am calling the SaveAs method of the FileUpload object. That method expects the full path file name of where you want to save on the hard drive. I save the uploaded images into an Uploads folder.
One thing you will notice is that I use a shared class instance variable named mPassedValidation in order for all of the methods to be able to communicate with each other. If any of the validation methods fail, they set that boolean variable to false, which prevents the saving of the uploaded file onto disk. To read more about class instance variables click here.
To summarize, there is a couple of things going on inside this web page. I have a control that is responsible for uploading a file to the web server. That control checks to ensure that all validation passed before it saves the file. Finally there are a couple of separate validation controls that actually perform the logic of ensuring that the file size is within a given desired range.
To watch a video of this example project actually running click here. See how I choose different files with different sizes and see how the program behaves.
So how do you intend to use the FileUpload or CustomValidator controls?
Nice article. It helped me a lot.
Thank you very much
Comment by horizon — March 20, 2009 @ 9:28 am
I did not find where you mention adding the textbox “txtResults” to the webform. The example code snippet for btnUpload_Click in the article has dropped some backslashes (”\upload\” should be “\\upload\\” and “rn” should be “\r\n”).
I am enjoying your lessons.
Comment by Chuck — April 17, 2009 @ 5:05 pm
any file larger than the code specified does not work..is there any other means to limit a file upload pls?
Comment by stefan — April 23, 2009 @ 8:19 am
Stefan,
Change the maxRequestLength value in your application’s web.config file. You can change it to 8MB by specifying maxRequestLength=”8192″. maxRequestLength is a property inside the httpRuntime node. httpRuntime is inside the system.web node
Comment by ted — April 24, 2009 @ 8:31 am
This is very good example. there is a minor mistake in above code put \r\n instead of rn. hope u never mind.
Thank you
Comment by — May 10, 2009 @ 10:44 pm
Why are you using mPassValidation rather than Page.IsValid? The Page.IsValid calculated from all validation controls, including the args.IsValid that you set in your code.
Comment by — May 11, 2009 @ 1:41 am
I use FileUpload feature in many pages but the issue i am having is, after doing successful upload try refreshing the page, you will notice that the same file will be uploaded once again….
is there any solution of this???
Comment by Srikanth — May 11, 2009 @ 9:14 am
can we upload vedio files and save those files in one folder in our application?
Comment by aashish — May 12, 2009 @ 5:24 am
I am having a problem with the browsed file name and path being cleared on error (if not correct file extension). I notice your example/video also clears on error. Any way around this?
Comment by Scott — May 12, 2009 @ 8:58 am
Jay, thanks for your comment about the backslash. I fixed it!
Comment by ted — May 14, 2009 @ 8:22 am
Rob, good point and thanks for your input. For this example I could have used the Page.IsValid property. In case you only wanted to check if a specific set of validation rules passed before saving the file, you could use the technique outlined here with the mPassValidation instance variable.
Comment by ted — May 14, 2009 @ 8:28 am
Srikanth,
When the file upload is complete, try redirecting back to the same page like
Response.Redirect(”yourpage.aspx”)
That should eliminate the data that is cached in the browser between pages.
Comment by ted — May 14, 2009 @ 8:40 am
Ted, you could use the mPassedValidation, but again there seems to be a better option. Each validator keeps its status, so you can use Page.IsValid for all validation and then use CustomValidator.IsValid to check the specific validators.
Maybe I’m missing something, but mPassValidation seems to be simply duplicating work already done for you by the framework.
Comment by — May 14, 2009 @ 9:21 am
Thanks for your helpful post
Comment by — May 18, 2009 @ 7:19 am
I have a client who wants to restrict filesize to 7MB. But the postedfile.ContentLength is integer so that maxes out at 2MB!
It looks liek to me that in general you should check the Stream length… but does that cause the stream to be opened and consumed? I don’t want my check method to actually cause an upload of the file until after I have checked the length.
I know it’s common for Web servers to default to a max upload of 2MB, but it seems strange int this age to use an integer to represent a file size in any situation.
Comment by — May 18, 2009 @ 3:06 pm
Thanks Chris,
First look at comment #4 in the blog post.
To restrict the file size to 7MB, set the maxRequestLength in your web.config file to “7168″. The maxRequestLength variable’s value is specified in KB, so you can multiply 1024 * [MAX file size in MB] to determine what to put in this variable.
Even though the file will be uploaded into RAM, it will NOT be saved to the hard drive if the validation rules fail. So it is as though the file was not uploaded.
Comment by ted — May 18, 2009 @ 6:23 pm
its giving an error in web.config on line no 78 to i.e
Error 68 Child nodes not allowed. (C:\Documents and Settings\sajid\Desktop\Check This FirstLab16_csharpuniversity\Lab16_csharpuniversity\web.config line 78)
Comment by sajid — May 27, 2009 @ 4:25 am
Chris,
An int can hold values from -2,147,483,648 to 2,147,483,647. That means that ContentLength can specify up to 2GB, not 2MB.
As for checking the size of the file before an upload occurs, that would require you to have code running on the client. Think Java applet or embedded ActiveX or .NET control. What Ted is showing here is server-side code. At the point his code is running, the file has already been sent as part of the HTTP POST.
Comment by Tom — June 4, 2009 @ 8:24 am
Hi,
Thanks a lot for ur article.. it helped me a lot…. realized lot many mistakes in my programming style…
Cheers!!!
Comment by — August 29, 2009 @ 1:05 am
One thing to consider with FileUpload is that you can update the control properties like FileUpload.FileName without causing EventValidation to trigger. This allows you to provide an empty ViewState and no EventValidation and the Page.IsPostBack will return true and the request will work even if you try to mitigate against CSRF using Page.ViewStateUserKey.
Comment by Sacha — August 31, 2009 @ 3:27 pm
Hi,
Thanks a lot for your article…i want to upload multiple files at a time nearly 100.is it possible to do so….can you help me.
Comment by prabhakar — September 19, 2009 @ 4:59 am
It is a great tutorial.
This worked great locally, but as soon as I tested it live I have permission’s deny error.
What are the proper permissions for an upload folder with IIS?
And how can I keep secure my website if I give IUser write permission?
Thanks
Comment by — November 28, 2009 @ 10:32 pm
Some one please help me out. Once after selecting the file by using browse file upload, onchange event how can i call server side code.
Comment by Sajan — March 15, 2010 @ 4:10 pm