Back in the ASP world uploading files via a web page was a tricky problem. The problem was that due to the encryption type of the form used to submit the file from the client’s browser receiving such files on the server side was a complex task. Data had to be retrieved as a safe byte array and decrypted before it could be used. Most of the people resorted to 3rd party DLL’s, a few wrote their own DLL’s and some even wrote purely ASP solutions to this problem using VBScript. Fortunately for us, .NET Framework SDK comes with a few classes that make uploading of the files simple from the web developer point of view.
This article will demonstrate following concepts:
How to setup a form for file uploading.
How to receive uploaded file on the server side.
How to save uploaded file to hard drive.
How to save uploaded file in database.
How to retrieve a file that is stored in database and return it to a client.
Security considerations running the demo project.
Setting up HTML form for file uploading.
The requirements for HTML form to be able to upload files are very simple: you have to use multipart/form-data encryption and you have to use method of post.
HTML input control that is used to upload file has a simple type of<form id="Form1" method="post" runat="server" enctype="multipart/form-data">
file This is all that needs to be done to HTML form for a client to be able to submit a file to your ASP.NET application.<input id="filMyFile" type="file" runat="server">
Receiving uploaded file.
<INPUT TYPE=”file” corresponds to System.Web.UI.HtmlControls.HtmlInputFile type of object on the server side. So if you like myself are using a CodeBehind architecture for your page you will have a member field definition similar to this in your class:
protected HtmlInputFile filMyFile;
HtmlInputFile class have a few different properties, but only one that really concerns us here is PostedFile. This property will tell us all we need to know about the file that had been uploaded to our server. PostedFile property is null if no file was submitted by a client. So we can simply check whether file was sent by doing something like this: if( filMyFile.PostedFile != null )
{
// File was sent
}
else
{
// No file
}
PostedFile property will contain a valid System.Web.HttpPostedFile object if file indeed was uploaded. HttpPostedFile provides us with 4 properties:
ContentLength – size of uploaded file in bytesContentType – MIME type of uploaded file, i.e. “image/gif”FileName – full path to uploaded file on client’s system, i.e. c:\Some folder\MyPicture.gifInputStream – stream object that gives us access to uploaded data.
Now that we know the size we can move on to retrieving the data. First we need to allocate a byte array to store the data:// Get a reference to PostedFile object
HttpPostedFile myFile = filMyFile.PostedFile;
// Get size of uploaded file
int nFileLen = myFile.ContentLength;
Next we can read uploaded file in our buffer using// Allocate a buffer for reading of the file
byte[] myData = new byte[nFileLen];
InputStream object: At this point we successfully retrieved uploaded file into a byte array called myData. What to do with it next depends largely on the requirements of your application I will show both saving the file to hard drive and to a database in the next sections.// Read uploaded file from the Stream
myFile.InputStream.Read(myData, 0, nFileLen);
Saving uploaded file to disk
I wrote a simple function for my demo project that stores files to a disk:
I pass a full path of where I want file to be stored and reference to a buffer with file data to this function. It uses// Writes file to current folder
private void WriteToFile(string strPath, ref byte[] Buffer)
{
// Create a file
FileStream newFile = new FileStream(strPath, FileMode.Create);
// Write data to the file
newFile.Write(Buffer, 0, Buffer.Length);
// Close file
newFile.Close();
}
System.IO.FileStream object to write buffer to a disk.
This very simplistic 3 lines of code approach will work in most cases. Couple of considerations here are: getting filename of uploaded file and security. Since FileName property of PostedFile is a full path to uploaded file on a client’s computer we will probably want to use only the filename portion of that path. Instead of using some parsing techniques to look for backslashes and things like that we can use very convenient little utility class - System.IO.Path.
Security is another matter. In my demo project I store files in the same folder where project is executed. In order for that to work ASPNET account (account that is used to execute ASP.NET processes) has to have Write permissions on that folder. By default it does not, so you need to right-click the folder, go to security tab and add ASPNET account to the list, then grant write permissions to that account (by checking Write checkbox) and click OK.string strFilename = Path.GetFileName(myFile.FileName);
Saving uploaded file to database
Following function is used in my demo project to store uploaded file in the database:
Access database that I used in demo project has only one table// Writes file to the database
private int WriteToDB(string strName, string strType, ref byte[] Buffer)
{
int nFileID = 0;
// Create connection
OleDbConnection dbConn = new OleDbConnection(GetConnectionString());
// Create Adapter
OleDbDataAdapter dbAdapt = new OleDbDataAdapter("SELECT * FROM tblFile", dbConn);
![]()
// We need this to get an ID back from the database
dbAdapt.MissingSchemaAction = MissingSchemaAction.AddWithKey;
![]()
// Create and initialize CommandBuilder
OleDbCommandBuilder dbCB = new OleDbCommandBuilder(dbAdapt);
// Open Connection
dbConn.Open();
![]()
// New DataSet
DataSet dbSet = new DataSet();
![]()
// Populate DataSet with data
dbAdapt.Fill(dbSet, "tblFile");
// Get reference to our table
DataTable dbTable = dbSet.Tables["tblFile"];
// Create new row
DataRow dbRow = dbTable.NewRow();
// Store data in the row
dbRow["FileName"] = strName;
dbRow["FileSize"] = Buffer.Length;
dbRow["ContentType"] = strType;
dbRow["FileData"] = Buffer;
// Add row back to table
dbTable.Rows.Add(dbRow);
// Update data source
dbAdapt.Update(dbSet, "tblFile");
// Get newFileID
if( !dbRow.IsNull("FileID") )
nFileID = (int)dbRow["FileID"];
![]()
// Close connection
dbConn.Close();
// Return FileID
return nFileID;
}
tblFile that has 5 fields defined as follow:
FileID – autonumber
Filename – text 255
FileSize - long integer
ContentType – text 100
FileData – OLE Object
The code in the above function is very straight forward. I create OleDbConnection, OleDbDataAdapter and DataSet objects and then append a row to the only table in DataSet. The important thing to note here is that OleDbCommandBuilder object needs to be created and initialized with a reference to OleDbDataAdapter object to build the insert query for us automatically. Also if you would like to retrieve newly assigned FileID of the file you have just stored in the database you need to make sure you set MissingSchemaAction property of Adapter to MissingSchemaAction.AddWithKey. That assures that Primary Key/autonumber FileID field will be populated with new ID when you call Update method of your DataAdapter.
Local ASPNET account has to have write permissions to a database file in order for your code to succeed. If you file is placed anywhere under wwwroot you will need to manually give database file all the necessary permissions before running my demo project.
Retrieving of a file from database.
I used the same aspx page to read and return file data out of the database in my demo project. I check for FileID parameter being passed to a page. If it was passed I know that I need to return a file rather than process user’s input:
private void Page_Load(object sender, System.EventArgs e)
{
// Check if FileID was passed to this page as a parameter
if( Request.QueryString["FileID"] != null )
{
// Get the file out of database and return it to requesting client
ShowTheFile(Convert.ToInt32(Request.QueryString["FileID"]));
}
![]()
}
ShowTheFile function does all the work here: I am using// Read file out of the database and returns it to client
private void ShowTheFile(int FileID)
{
// Define SQL select statement
string SQL = "SELECT FileSize, FileData, ContentType FROM tblFile WHERE FileID = "
+ FileID.ToString();
// Create Connection object
OleDbConnection dbConn = new OleDbConnection(GetConnectionString());
// Create Command Object
OleDbCommand dbComm = new OleDbCommand(SQL, dbConn);
// Open Connection
dbConn.Open();
// Execute command and receive DataReader
OleDbDataReader dbRead = dbComm.ExecuteReader();
// Read row
dbRead.Read();
// Clear Response buffer
Response.Clear();
// Set ContentType to the ContentType of our file
Response.ContentType = (string)dbRead["ContentType"];
// Write data out of database into Output Stream
Response.OutputStream.Write((byte[])dbRead["FileData"], 0, (int)dbRead["FileSize"]);
// Close database connection
dbConn.Close();
// End the page
Response.End();
}
OleDbConnection, OleDbCommand and OleDbDataReader objects to retrieve data. Next thing is to clear Response output buffer to make sure that no other information is being sent to client beside our file data. That will only work if buffering of your pages is turned on (default in ASP.NET). I set ContentType property of Response object to the content type of our file and then I write file data into Output stream of Response object. The important thing here is to call Response.End() at the end to prevent farther processing of this page - we are done here and we do not want for other code to execute.
Security considerations
Important:
Because my demo project writes files to disk or data to an Access database you need to make sure that security permissions are set properly on folders and files where you want to write. Beta versions of .NET used System account to execute ASP.NET processes and it had access to everything on your computer. However, final release of .NET runs all ASP.NET processes under local ASPNET account. That account needs to have write permissions to all the folders and files that are being used to write data.
In order to make my demo project work under .NET release version you need to place it in a folder (anywhere under wwwroot) and set permissions of that folder as follow: Right-Click the folder, go to Properties, Security tab, make sure local ASPNET account have Read and Write permissions on that folder. If not, Add local ASPNET account to the list and give it read and write permissions. Click OK.






}
浙公网安备 33010602011771号