Skip to main content

Uploading files to the server like GMail and Yahoo Mail


Recently I got to work on a project which needed file uploading just like in GMail and Yahoo Mail. Before proceeding further, I would like to mention that it is not possible to use AJAX to do file uploading to ther server as JavaScript can execute only in the browser and does not have access to the file system. So the technique we employed here is the the hidden IFrame .


To make this work we need JavaScript and any server side script. For the demo, I will be using ASP.NET with C# on the server side.


Let us delve in to the code without further delay.


Step 1: In your web application, create two aspx files UploadTest.aspx and UploadFile.aspx.

Step 2: Add this HTML code inside form tag to UploadTest.aspx

<table id="tblAttach">

<tr>


<!--- This td displays the link Attach File-->


<td id="td_upload_attach" style="DISPLAY: block;></td>


<!--This td displays the attaching message while the file is uploading to ther server-->


<td id="td_upload_attaching" style="DISPLAY: none"> </td>

<!--This td displays the attached file-->

<td id="td_upload_fileName" style="DISPLAY: none"></td>


<!--This td displays the Remove Link-->


<td id="td_upload_remove" style="DISPLAY: none"></td>

</tr>

</table>


Step 3: Update the first td to add an image and Attach File link and hidden IFrame. Clicking on Attach File link will call the javascript function AttachFile() (discussed later).



The hidden IFrame's source is set UploadFile.aspx that we created above.


<td style="DISPLAY: block;" id="td_upload_attach">


<table width="100" border="0" cellpadding="2" cellspacing="0">


<tr>


<td width="16"><img src="paperclip.gif" width="16" height="16"></td>


<td nowrap align="left" class="blackFormText2"><a href="#" tabindex="12" class="blackFormText2" onclick="AttachFile();">Attach File</a></td> </tr> </table>


<iframe id="iFrameUpload" style="DISPLAY: none;" width="50" height="50" align="top" marginWidth="1" marginHeight="1" frameBorder="no" scrolling="no" src="UploadFile.aspx"> </iframe>


</td>


Step 4: Update the second td to add code that displays a rotating icon and a message attaching... while the file is uploading to the server.


<table width="100" border="0" cellpadding="2" cellspacing="0">


<tr>


<td width="16"><img src="loading_small.gif" width="16" height="16"></td>


<td nowrap class="blackFormText" style="WHITE-SPACE:nowrap"><span id="span_upload_attaching">Attaching...</span></td>


</tr>


</table>


Step 5: Update the third td to add an image and the attached file name.


<table width="100" border="0" cellpadding="2" cellspacing="0">


<tr>


<td width="16"><img src="attached.gif" width="14" height="16"></td> <td nowrap class="blackFormText2"><span id="span_upload_fileName"></span></td> </tr>


</table>


Step 6: Update the fourth td to add a remove image and a link to remove the attached file.


<td id="td_upload_remove" style="DISPLAY: none">


<table width="100" border="0" cellpadding="2" cellspacing="0">


<tr>


<td width="16"><img src="remove.gif" width="14" height="16"></td>


<td nowrap class="blackFormText2"><a tabindex="12" href="#" class="blackFormText" onclick="RemoveFile();">Remove File</a> </td>


</tr>


</table>


</td>

Step 7: Now, let us discuss the javascript needed to accomplish our task. Add javascript script block inside the head section of the web form. Add two variable fileId and fileName;

<Script language="javascript">

var fileId=-1;

var fileName="";

</Script>


Step 8: Add the function AttachFile() inside the javascript block. When the user clicks the Attach File link, this function is called.


function AttachFile()


{


var uploadFrame=window.frames["iFrameUpload"].document;


uploadFrame.forms[0].txtFileToUpload.click();


if(uploadFrame.forms[0].txtFileToUpload.value!='')


{


var filePath=uploadFrame.forms[0].txtFileToUpload.value;


var fileNameIndexStart=filePath.lastIndexOf("//");


var fileName=filePath.substring(fileNameIndexStart+1,filePath.length);


document.getElementById('td_upload_attach').style.display='none';


document.getElementById('span_upload_attaching').innerHTML=


'attaching... '+fileName;


document.getElementById('td_upload_attaching').style.display='block';


uploadFrame.forms[0].submit();


}


}


Step 9: Add the function AttachFile_Callback(). This function is called by the UploadFile.aspx after attaching the file. Any errors reported by the UploadFile.aspx, are displayed to ther user.

Error Ids are set on the server side when an error is encounterd. (Discussed on Step 17)


function AttachFile_Callback(errorId,id,name)


{


if(errorId.length>0)


{


document.getElementById('td_upload_attach').style.display='block';


document.getElementById('td_upload_attaching').style.display='none';


switch(errorId)


{ case "1": window.parent.alert("Please select a file to upload");


break;


case "2": window.parent.alert("The uploaded file is empty");


break;


case "3": window.parent.alert("The uploaded file is too big. The file size cannot be greater than 5 MB.");


break;


case "4": window.parent.alert("Sorry, an unexpected error occurred uploading the file.");


break;


}


}


else if(id!="-1")


{


fileId=id; //set the file Id; fileName=name;


var spanFileName=document.getElementById('span_upload_fileName');


if(spanFileName!=null)


{ spanFileName.innerHTML=name; }


ShowUploadLink(false);


}


}



Step 10: Add the function RemoveFile(). This shows the attach file link again. I have not added code to remove the file on the server. If necessary you can add that here. You can pass the id of the file that we put in the global variable fileId to the server.


function RemoveFile() { ShowUploadLink(true); }


Step 11: Add the function ShowUploadLink(). This is a helper function to show and hide <td>s in the table.


function ShowUploadLink(flag)


{


var tdAttach=document.getElementById('td_upload_attach');


var tdAttaching=document.getElementById('td_upload_attaching');


var tdFileName=document.getElementById('td_upload_fileName');


var tdRemove=document.getElementById('td_upload_remove');


if(flag)


{


tdAttach.style.display='block'; tdAttaching.style.display='none';


tdFileName.style.display='none'; tdRemove.style.display='none';


}


else


{ tdAttach.style.display='none'; tdAttaching.style.display='none';


tdFileName.style.display='block'; tdRemove.style.display='block';


var spanFileName=document.getElementById('span_upload_fileName');


if(spanFileName!=null)


{ spanFileName.innerHTML=fileName; }


}


}



Step 12:


Now let us add code to the UploadFile.aspx. Add an input of type file.


<table width="100%" border="0" cellpadding="6" cellspacing="0" bgcolor="#e1ecf2" summary="This table is for layout">
<tr>
<td valign="top">
<input class="blueFormText" id="txtFileToUpload" title="File to Upload"
tabindex="200" type="file" size="30" name="filMyFile" runat="server" style="WIDTH: 275px; HEIGHT: 22px">
</td>
</tr>
</table>


Step 13:


Add three hidden variables to the web form.


<INPUT id="hidFileName" type="hidden" runat="server" NAME="hidFileName" class="blueFormText"> <INPUT type="hidden" runat="server" id="hidFileId" NAME="hidFileId" class="blueFormText" value=-1> <INPUT id="hidErrorId" type="hidden" runat="server">


Step 14:


To the body tag of the web form add onload event.


<body MS_POSITIONING="GridLayout" onload="CheckFileId();">


Step 15:


Add the javascript function that is called by onload event. This function calls AttachFile_Callback function we added above when ever this page is loaded in the browser.


<script language="javascript">

function CheckFileId()

{

var hidErrorId=document.getElementById('hidErrorId');

var hidFile=document.getElementById('hidFileId');

var hidFileName=document.getElementById('hidFileName');

window.parent.AttachFile_Callback (hidErrorId.value,hidFile.value,hidFileName.value); }

</script>


Step 16:


In the code behind of the UploadFile.aspx, in Page_Load(), I check if the page is posted back and call the UploadFile function that takes cared of adding the file to the database.


private void Page_Load(object sender, System.EventArgs e)
{
if(Page.IsPostBack)
UploadFile();
}


Step 17:


Add code for UploadFile server side function. The function checks for erorrs like 0 length, more than 5 MB and unexpected errors. If no errors file is put into the database.


private void UploadFile()
{
//check if the user selected a file.
if(txtFileToUpload.PostedFile.FileName.Trim() == null txtFileToUpload.PostedFile.FileName.Trim().Length == 0)
{
hidErrorId.Value="1";
return;
}
int intDocLen = txtFileToUpload.PostedFile.ContentLength;
if(intDocLen==0)
{
hidErrorId.Value="2";
return;
}
if(intDocLen>5000000)
{
//Response.Write("Please limit the file size to 5MB.");
hidErrorId.Value="3";
return;
}
try
{
string fileName=System.IO.Path.GetFileName(txtFileToUpload.PostedFile.FileName);
int fileLength=txtFileToUpload.PostedFile.ContentLength;
string fileType=txtFileToUpload.PostedFile.ContentType;
byte[] fileBin=new byte[fileLength];
System.IO.Stream stream = txtFileToUpload.PostedFile.InputStream;
stream.Read(fileBin,0,fileLength);
string connstr=util.WebConfigReader.GetAppSetting(model.Constants.CONNECTION_STRING_KEY); //change connection string
SqlConnection connection = new SqlConnection(connstr);
string sql="INSERT Into FileTable(FileName,Filetype,FileBin)Values(@FileName,@FileType,@FileBin);SELECT SCOPE_IDENTITY();"
SqlCommand insertCommand = new SqlCommand(sql,connection);


SqlParameter fileNameParam = new SqlParameter("@FileName", SqlDbType.VarChar);
fileNameParam.Value = fileName;
insertCommand.Parameters.Add(fileNameParam);

SqlParameter fileTypeParam = new SqlParameter("@FileType", SqlDbType.VarChar);
fileTypeParam.Value = fileType;
insertCommand.Parameters.Add(fileTypeParam);

SqlParameter fileBinParam = new SqlParameter("@FileBin", SqlDbType.Image);
fileBinParam.Value = fileBin;
insertCommand.Parameters.Add(fileBinParam);

connection.Open();
string fileId = insertCommand.ExecuteScalar().ToString();;
connection.Close();

hidFileId.Value=fileId;

hidFileName.Value=fileName;
}
catch(Exception ex)
{

hidErrorId.Value="4";
}
}

Comments

Popular posts from this blog

Clear Validation Errors and Validation Summary messages

ASP.net built in validation does not provide us a straight forward to clear all the validation errors. This would be really helpful while resetting a form. The reset html button would simply reset the form values but will not clear the validation errors. The following javascript code snippet can be used to clear the validation error messages. Have a reset button on your form and call the following js function onclick. <input type="reset" onclick="HideValidationErrors();" /> function HideValidationErrors() { //Hide all validation errors if (window.Page_Validators) for (var vI = 0; vI < Page_Validators.length; vI++) { var vValidator = Page_Validators[vI]; vValidator.isvalid = true; ValidatorUpdateDisplay(vValidator); } //Hide all validaiton summaries if (typeof (Page_ValidationSummaries) != "undefined") { //hide the validation summaries

Kill a remote user session remotely

When trying to connect to your Windows 2000/2003 server remotely, you may receive the following error. "The terminal server has exceeded the maximum number of allowed connections." You could kill one or more of those connections by using PsExec tool that can be downloaded from the following link. This tool and a bunch of others were developed by SysInternals which was bought by Microsoft. http://www.microsoft.com/technet/sysinternals/utilities/pstools.mspx Open your command prompt and from the directory that contains the psexec utility, do the following 1) psexec \\x.x.x.x -u user -p password cmd (this will give you access to the cmd prompt on the server) Example: psexec \\127.0.0.1 -u admin -p password cmd 2) once you get the command prompt run the command qwinsta to get a list of all Terminal Services connections. Each connection has an Id Number. 3) Run the command logoff [id# of session to quit] /v (this will kill the connection with that id #) Example: logoff 2 /v Once

Creating a Windows Task Scheduler Service

Recently, one of my friends asked me for help in creating a windows service for scheduling some tasks. He said that he could not use the task scheduler that comes with Windows as the Task Scheduler expects each task to be a stand alone executable file. All his tasks were in a single class library and it would be a lot of work to separate each task into its own executable. Also he said that that the schedule for the tasks could change from time to time and it would be nice if he could configure the tasks in an XML file. To Recap, the requirements for the windows service are 1) The tasks should be loaded from a class library 2) The schedule information for the tasks should be configurable in an XML file. We googled (binged :)) for the solution and found an excellent article by Ajit Kumar Application Scheduler Service Using C#.Net And XML to base our solution upon. We took some good points like configuring the task information from the above mentioned article. This is how we to