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 ...

Find the cause of poor performance in Sql Server

I found the following two part article by Gail Shaw on Simple-Talk really helpful in trouble shooting poorly performing queries in Sql Server. The articles talks about spotting poorly performing queries with the help of the Profiler, understand Sql Server Query plans and fine tune the peformance using proper indexes. Part 1: http://tinyurl.com/ccl6gj Part 2: http://tinyurl.com/okcuqg

SharePoint: Comparing dates in XSLT

In one of my sharePoint projects, I had to compare a date with the current date in XSLT. As it turned out, there is no support for date comparision in XSLT. This is how I went about doing it. The trick involves converting the date string into a number Say the date is in ISO format YYYY-MM-DDTHH:MM:SSZ (for example, 2001-01-21T22:54:47Z). Say we have a variable DueDate <xsl:variable name="DueDate" select="'2001-01-21T22:54:47Z'"> Replace the dashes in the string with empty string Take the first 10 character in the date sring convert the string to number number(translate(substring(@DueDate,1,10),'-','')) On doing the above we get: 20010121 We can do the same thing with the date to compare. We can compare the duedate with the current date in SharePoint as follows number(translate(substring(@DueDate,1,10),'-','')) & lt; number(translate(substring(ddwrt:TodayIso(),1,10),'-','')) You can apply the same log...