Saturday, July 08, 2006

 
File Upload in .Net 1.1

For copy/pasters or quick references, click here to jump straight to the full code.

Even though I classified this post as intermediate, there's a chance you might be a long-time programmer and never really needed to use this function (that was my case for a while after I started programming a long time ago).

Maybe you just assumed that there is a standard control that could be dropped onto your page and all you would have to do is capture some kind of "save" event if you ever needed to include file uploading on your page one day. Well, the good news is that this is true as of .Net 2.0 (finally!). The FileUpload control offers all that functionality and more. However, if you are using .Net 1.x I'm afraid you are going to have to work a bit harder.

On the other hand, if all you want is to save an uploaded file as a file in your local server as opposed to storing its bytes on a database, for instance, then there actually is a "save" function that will do all the dirty work for you. It just takes some set up before that can happen.

.Net 1.x doesn't have direct support for file uploading. You must therefore use the same <input type="file"> as you would on a regular html file and transform that into a server control by adding runat=server to its definition so you can manipulate it on the server-side. Let's look at this in detail.
1 - Setup

step 1:add a form The first requirement for implementing file uploading on your web page, whether it's just simple HTML, PHP, ASP.NET or whatever, is to have a form. Well, lucky you, if you are programming in .Net you already necessarily have that.

step 2:form's method must be "post" The second requirement is that the form uses the post method;again something that you probably don't have to worry about if you are using an IDE like Visual Studio or Dreamweaver to build your .Net pages since this is usually the default.

step 3: form's enctype must be "multipart/form-data"

Now this is where you have to really pay attention. The third and last requirement as far as "forms" are concerned is that you have to set the enctype attribute of the form to multipart/form-data. If you are using an IDE like Visual Studio or Dreamweaver, the enctype attribute is not added automatically for you to your form tags so you'll have to do that manually. This is absolutely necessary otherwise the uploads will always fail and you will get an error on your page if you try to submit. Something like:

Form was submitted with no enctype="multipart/form-data"
Please correct the form attributes and try again.

So, in one easy step, on your aspx page so far your form tag should be looking like this:


<form action="me.aspx" method="post" enctype="multipart/form-data">



step 4: add an input field to the form of type file
Now, all you need to do is add a standard HTML input element to your form of type file, give it some id and transform it into a server control, like this:

<input type="file" id="upload_control" runat="server">


Note that so far everything we have done was just standard HTML, except for adding the runtat=server to the input tag.

step 5: declare the field on your code-behind
Now we have to declare our input field on our code-behind so we can manipulate it.
The input field of type file maps to the HtmlInputFile control which belongs to the HtmlControls namespace.
So in your code-behind, add the following declaration:

Vb.Net
Protected upload_control as As System.Web.UI.HtmlControls.HtmlInputFile

C#
protected HtmlInputFile file_whatever;


2-Receiving The File

By now, if you followed the steps above, you have a web page which allows the user to browse his computer for files and upload it to the server by submitting the form. That's right, all the uploading job is done for you automatically. All you have to do is learn how to save this data to whatever medium it is you want. Mediums include saving to a file or directly to a database BLOB column, for instance. Although the latter will not be covered here, even because I strongly discourage such practice, I will show you how to get the content of the file in bytes so you can do as you please with it as well as showing you how to just save the contents to a file on your local server, which is not only what I reccomend but also it's much simpler actually. You should always avoid storing binary data on the database if possible since they weren't really made for that and it generates unnecessary overhead. In the case of storing images, I am a big advocate of saving it locally and only storing the path to the file on the database.

step 6: getting information about the file uploaded with HttpInputFile
Now, there is only one property that really matters of the HttpInputFile: PostedFile. This property returns an object of type HttpPostedFile which contains all information about the file uploaded. If no files were uploaded then it returns null.
So, we should check to see if anything was uploaded at all before anything else, and if so then we can grab our HttpPostedFile and move on.


review: upload_control is the id of our HttpInputFile, as declared previously

VB.Net
Dim file as HttpPostedFile
file = upload_control.PostedFile
if file is nothing then
'do nothing
else
'DO FILE READING AND SAVING HERE
end if

C#
HttpPostedFile file;
file = upload_control.PostedFile
if (file == null)
{
//do nothing
}
{
//DO FILE READING AND SAVING HERE
}



Exploring: HttpPostedFile
Before moving on to the next steps, let's familiarize ourselves with the HtmlInputFile control.
It is important to know that the "currency" when dealing with files is always bytes, that is we are dealing with files on the lowest level: a sequential sequence of bytes.

The three properties that stand out for this control are:
So what we are going to do next is get our HttpPostedFile and play with it in order to receive and save our file.

step 7: saving the file (...finally!)
From here on everything is much more straight-forward .Net stuff. Once you get your HttpPostedFile, you've pretty much done everything that has to do in particular with uploading files; now ayou have two choices: if you want to save to a file then all you have to do is invoke the SaveAs method of the HttpPostedFile and pass in a string with the path and name of the file you want to create. However, if you intend to do anything else with the file then you are going to have to play with streams to save the data by using the HttpPostedFile input stream.
Here's how to do it both:

Saving to a file

VB.Net and C#
file.SaveAs("fileNameYouWantToGive")
or
Getting the file content in bytes

review: file is our HttpPostedFile object as retrieved in the last step by using the HttpInputFile.HttpPostedFile property

VB.Net
Dim length As Integer

Dim fileName As String = ""

file = file_publication.PostedFile
'====get the length for the file
length = file.ContentLength
'create a byte array which will be populated with all the bytes from the file
'this array can then be passed to the Write function of a FileStream object
'in order to create a local file on your server
Dim data(length) As Byte
'==========get the filename
'remember:the FileName property of HttpPostedFile
'is tricky; it returns the full path of the file as it was on the
'computer of the user who uploaded the file
'fortunately the shared function of the Path class called GetFileName does just that!
fileName = Path.GetFileName(file.FileName)

'read the content of the file(its bytes) into our byte array
file.InputStream.Read(data, 0, length)

'data now contains the whole content for the file
'and you may do as you please with it

C#
int length = 0;

String fileName = "";


file = file_publication.PostedFile
//====get the length for the file
length = file.ContentLength
//create a byte array which will be populated with all the bytes from the file
//this array can then be passed to the Write function of a FileStream object
//in order to create a local file on your server
Byte data[length];
//==========get the filename
//remember:the FileName property of HttpPostedFile
//is tricky; it returns the full path of the file as it was on the
//computer of the user who uploaded the file
//fortunately the shared function of the Path class called GetFileName does just that!
fileName = Path.GetFileName(file.FileName)

//read the content of the file(its bytes) into our byte array
file.InputStream.Read(data, 0, length)


'data now contains the whole content for the file
'and you may do as you please with it





And that's it!

Now, for you inpatient, copy/pasters or just simply practical ones, here is the full code with no dissecting or long explanations (though it still contains some comments to help you out):

FULL CODE:


upload.aspx:

<form id="form1" method="post" enctype="multipart/form-data">
<input id="upload_control" runat="server" type="file">
</form>




note: the code for receiving the file has been conviniently modularized
into a fucntion named receiveFile() so you may call it wherever you want in your code, such as the Page_Load event, for example.

VB.Net

upload.vb
Protected upload_control as As System.Web.UI.HtmlControls.HtmlInputFile

private sub receiveFile()
Dim file as HttpPostedFile

file = upload_control.PostedFile
if file is nothing then
'do nothing
else
'IF YOU JUST WANT TO SAVE TO A FILE
file.SaveAs("whateverNameYouWantToGiveToTheFile")

'IF YOU NEED TO READ THE CONTENT IN A BUFFER
Dim length As Integer
'create a byte array which will be populated with all the bytes from the file
'this array can then be passed to the Write function of a FileStream object
'in order to create a local file on your server
Dim data(length) As Byte
Dim fileName As String = ""

'====get the length for the file
length = file.ContentLength
file = file_publication.PostedFile
'==========get the filename
'remember:the FileName property of HttpPostedFile
'is tricky; it returns the full path of the file as it was on the
'computer of the user who uploaded the file
'fortunately the shared function of the Path class called GetFileName does just that! This is not a necessary step it's only here to show you how to do it
fileName = Path.GetFileName(file.FileName)

'read the content of the file(its bytes) into our byte array
file.InputStream.Read(data, 0, length)

'data now contains the whole content for the file
'and you may do as you please with it


end if
end sub


note: the code for receiving the file has been conviniently modularized
into a fucntion named receiveFile() so you may call it wherever you want in your code, such as the Page_Load event, for example.

C#
protected HtmlInputFile file_whatever;

HttpPostedFile file;
file = upload_control.PostedFile
if (file == null)
{
//do nothing
}
else
{

'IF YOU JUST WANT TO SAVE TO A FILE
file.SaveAs("whateverNameYouWantToGiveToTheFile")


'IF YOU NEED TO READ THE CONTENT IN A BUFFER
int length = 0;
//create a byte array which will be populated with all the bytes from the file
//this array can then be passed to the Write function of a FileStream object
//in order to create a local file on your server
Byte data[length];
String fileName = "";

//====get the length for the file
length = file.ContentLength
file = file_publication.PostedFile
//==========get the filename
//remember:the FileName property of HttpPostedFile
//is tricky; it returns the full path of the file as it was on the
//computer of the user who uploaded the file
//fortunately the shared function of the Path class called GetFileName does just that!This is not a necessary step it's only here to show you how to do it
fileName = Path.GetFileName(file.FileName)

//read the content of the file(its bytes) into our byte array
file.InputStream.Read(data, 0, length)

'data now contains the whole content for the file
'and you may do as you please with it
}
}

Comments: Post a Comment



<< Home

This page is powered by Blogger. Isn't yours?