HTML5 File Drag and Drop Upload With jQuery and ASP.NET

28. January 2012 12:00

ASP.NET HTML5 Jquery Web 

I came across an article on Tutorialzine which demonstrate file drag and drop upload with jQuery and PHP. As a curious reader, I downloaded the sample files and took a look and also get it running on my LINUX VM. It worked like a charm. But I am a Windows user and .NET programmer, the question is how can I do the same in ASP.NET?

If someone out there can do something in PHP then I can do that in .NET!!

Who said the above line??.....ME!!??.....oh yeah!!! So, to get myself started I used the same downloaded files that I used to check the PHP version of the file drag and drop. The only thing that we are not going to re-use out of these files is the php file. You can delete it if you wish or keep it, it's of no harm to our ASP.NET app.

Updating The jQuery Part

This example uses an awesome plugin from Weixi Yen and you can found the plugin and it's sample usage (documentation) on GitHub. The basic or I should say the default functionality provided by this plugin is to allow users to drag and drop the files from desktop to the browser. But before you actually get started with the plugin, I strongly recommend that you make yourself familiar with the parameters and configurations of the plugin.

Open the script.js file and change the URL to point to the web service or the page which will upload the posted file. Here I want you to pay attention to the javascript function named createImage. This method accepts the file as a parameter and returns the image or file data in Base64 format. This is the data which actually gets posted when the user drops a file to the upload area on the web page. This is all up to you whether you want to use a web service or a normal web page to accept the posted file/data. Here is my script.js file looks like after the changes.

$(function () {

    var dropbox = $('#dropbox'),
		message = $('.message', dropbox);

    dropbox.filedrop({
        paramname: 'pic',
        maxfiles: 5,
        maxfilesize: 100,
        //url: '/Uploader.asmx/Upload',
        url: '/Default.aspx',

        uploadFinished: function (i, file, response) {
            $.data(file).addClass('done');
        },

        error: function (err, file) {
            switch (err) {
                case 'BrowserNotSupported':
                    showMessage('Your browser does not support HTML5 file uploads!');
                    break;
                case 'TooManyFiles':
                    alert('Too many files! Please select 5 at most! (configurable)');
                    break;
                case 'FileTooLarge':
                    alert(file.name + ' is too large! Please upload files up to 2mb (configurable).');
                    break;
                default:
                    break;
            }
        },

        // Called before each upload is started
        //        beforeEach: function (file) {
        //            if (!file.type.match(/^image\//)) {
        //                alert('Only images are allowed!');

        //                // Returning false will cause the
        //                // file to be rejected
        //                return false;
        //            }
        //        },

        uploadStarted: function (i, file, len) {
            createImage(file);
        },

        progressUpdated: function (i, file, progress) {
            $.data(file).find('.progress').width(progress);
        }

    });

    var template = '<div class="preview">' +
						'<span class="imageHolder">' +
							'<img />' +
							'<span class="uploaded"></span>' +
						'</span>' +
						'<div class="progressHolder">' +
							'<div class="progress"></div>' +
						'</div>' +
					'</div>';


    function createImage(file) {

        var preview = $(template),
			image = $('img', preview);

        var reader = new FileReader();

        image.width = 100;
        image.height = 100;

        reader.onload = function (e) {

            // e.target.result holds the DataURL which
            // can be used as a source of the image:
            //alert(e.target.result);
            image.attr('src', e.target.result);
        };

        // Reading the file as a DataURL. When finished,
        // this will trigger the onload function above:
        reader.readAsDataURL(file);

        message.hide();
        preview.appendTo(dropbox);

        // Associating a preview container
        // with the file, using jQuery's $.data():

        $.data(file, preview);
    }

    function showMessage(msg) {
        message.html(msg);
    }

});

Check out line number 10 and 11. I have change the url parameter to the one where my files are going to be posted. It can be a webservice or just a normal web page. The other two parameters maxfiles and maxfilesize defines the number of file that can be uploaded asynchronously and maximum size of the file that can be uploaded in MBs respectively. Also note that the demo that you download from the original source will have a validation that the files that are being uploaded by the user should only be images. If you want to override this rule then uncomment the lines from 33-42. This is it from the jQuery/script part. Now time to move on the server side code.

The Server Side Code

To remind you again that we are posting a file to a web service or to a web page and therefore that code for our web service or on our page will look something like this:

If you are using a web service to upload the posted file:

[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string Upload()
{
       HttpContext postedContext = HttpContext.Current;
       HttpPostedFile file = postedContext.Request.Files[0];
       string name = file.FileName;
       byte[] binaryWriteArray = new
       byte[file.InputStream.Length];
       file.InputStream.Read(binaryWriteArray, 0,
       (int)file.InputStream.Length);
       FileStream objfilestream = new FileStream(Server.MapPath("uploads//" + name), FileMode.Create, FileAccess.ReadWrite);
       objfilestream.Write(binaryWriteArray, 0,
       binaryWriteArray.Length);
       objfilestream.Close();
       string[][] JaggedArray = new string[1][];
       JaggedArray[0] = new string[] { "File was uploaded successfully" };
       JavaScriptSerializer js = new JavaScriptSerializer();
       string strJSON = js.Serialize(JaggedArray);
       return strJSON;
}

Nothing fancy or complicated in the above code. Remember, the files will send to the web service one by one and not in a collection and this is the reason I am working with one file at a time and not with file collections. In my case I have used a web service that return me JSON result which I can show it to the user, though it is not necessary, but just in case if you want to have one for your web service you need to use 2 using statements:

  • using System.Web.Script.Serialization;
  • using System.Web.Script.Services;

If you are using a web page to upload the posted file:

HttpContext postedContext = HttpContext.Current;
HttpPostedFile file = postedContext.Request.Files[0];
string name = file.FileName;
byte[] binaryWriteArray = new
byte[file.InputStream.Length];
file.InputStream.Read(binaryWriteArray, 0,
(int)file.InputStream.Length);
FileStream objfilestream = new FileStream(Server.MapPath("uploads//" + name), FileMode.Create, FileAccess.ReadWrite);
objfilestream.Write(binaryWriteArray, 0,
binaryWriteArray.Length);
objfilestream.Close();
string[][] JaggedArray = new string[1][];
JaggedArray[0] = new string[] { "File was uploaded successfully" };
JavaScriptSerializer js = new JavaScriptSerializer();
string strJSON = js.Serialize(JaggedArray);
Response.Write(strJSON);
Response.End();

Same code as I have for the web service, put the above code on the page_load event.

Caution!!

While I was working around with the above code and configuration of the plugin I came across an error that won't allow me to upload heavy files or I should say large files. The error that I received is:

System.Web.HttpException: Maximum request length exceeded

To overcome this error you have make the below configuration in your web.config file inside <system.web>

<httpRuntime maxRequestLength="102400" executionTimeout="1200" />

A word of caution here, though it will solve your problem but:

  • If the maxrequestLength is TOO BIG then you will be open to DOS attacks.
  • The default executionTimeout is 360 seconds. Change it accordingly and only if you are running on really slow connections.

This is it, if you have followed the steps above then try uploading some file. And if you haven't and lazy to put all the pieces together then download the code from the below and try it.

Download: HTML5DragNDrpFileUpload.zip (58.15 kb)

Currently rated 4.4 by 13 people

Upload and Show Image Without Post Back With Jquery

11. October 2011 11:20

ASP.NET ASP.NET MVC Jquery Web 

Previously in a lot of hurry I wrote a post on how to upload files in MVC3 with the help of Uploadify, a famous jQuery plugin to upload files. If you have not heard about it yet, then it is time for you to check and find out what this plugin can do for you. Appending my last post about this plugin (which was not very well written) I tried one more thing with it today. This time I am trying to upload an image and then show it inside a DIV without a post back. If you have the source code from the previous post, then it will be good as you need not to start from the scratch.

I assume that you are a good designer as I am not. I am saying this because I really got a blank head in designing. Therefore it is up to you how you are going to show off the images on the page, I am just telling you a way to do that. I am using MVC3 for this example but it will work for both web forms and MVC. The only difference in MVC and web forms is in the server side code which is responsible to upload the file. If you are using MVC3 then your method to upload the file in the controller will be something like this:

public string Upload(HttpPostedFileBase fileData)
{
        var fileName = this.Server.MapPath("~/uploads/" + System.IO.Path.GetFileName(fileData.FileName));
        fileData.SaveAs(fileName);
        return "OK";
}

As we are using Uploadify, we now have to make changes in some of the parameters of the plugin. The Upload method is inside home controller, so the script parameter of the plugin will be /Home/Upload. For my convenience I have changed the multi and auto parameter to false and true respectively. By now this is the jQuery code I have:

<script type="text/javascript">
$(window).load(
function () {
    $("#fileuploader").fileUpload({
        'uploader': '/Scripts/uploader.swf',
        'cancelImg': '/Images/cancel.png',
        'buttonText': 'Select Image',
        'script': 'Home/Upload',
        'folder': '/uploads',
        'fileDesc': 'Image Files',
        'fileExt': '*.jpg;*.jpeg;*.gif;*.png',
        'multi': false,
        'auto': true
    });
}
);
</script>

In the end I append one more parameter onComplete which gets fired when the plugin finish uploading the file. To get the uploaded path of the image I am using fileObj.filePath and response to check if the file has been uploaded successfully or not. If the response I received after the uploading of the file is completed is ok then I will set the html to show the image in another DIV. Below is the complete configuration of the plugin.

<script type="text/javascript">
$(window).load(
function () {
    $("#fileuploader").fileUpload({
        'uploader': '/Scripts/uploader.swf',
        'cancelImg': '/Images/cancel.png',
        'buttonText': 'Select Image',
        'script': 'Home/Upload',
        'folder': '/uploads',
        'fileDesc': 'Image Files',
        'fileExt': '*.jpg;*.jpeg;*.gif;*.png',
        'multi': false,
        'auto': true,
        'onComplete': function (event, ID, fileObj, response) {
            if (response == "OK") {
                $("#uImg").addClass("loading");
                var htmlString = "<img src=\"" + fileObj.filePath + "\" alt=\"" + fileObj.name + "\" />";
                $("#uImg").html(htmlString);
                $("#uImg").removeClass("loading");
            }
        }
    });
}
);
</script>

Just to demonstrate I have placed an alert message box with the response which got fired on the onComplete event after the image has been uploaded successfully. After this I have created a html string which is actually a html img tag with src and alt tags. I have then set the same html string to another DIV which acts as a holder of the image being uploaded. Here is an output after the image is uploaded. Just to remind you, it is all done without post back.

This is it, try it yourself and I recommend you to check out the documentation of the plugin I used. Check out the other links below and one more thing that I would like you to do is to set the multi property of the plugin to true and the try uploading multiple images. If you end up making something awesome then do share with me/us.

Related Links:

Currently rated 4.6 by 8 people

Social Counter: JQuery Plugin To Get Twitter, Facebook And Feed Readers Count

2. September 2011 16:53

API ASP.NET Jquery Web 

Appending my previous post, I have created a plugin in JQuery to get twitter followers count, facebook likes and feed readers count. In my previous post, I have shown a way to get the counts in ASP.NET and I have created this plugin so that everyone can use and show counts on their blogs or site.
To get started add the two javascript files, one is the jquery file and the other one is the plugin file.
<script type="text/javascript" src="Scripts/jquery-1.4.1.js"></script>
<script src="Scripts/jquery.SocialCounter.js" type="text/javascript"></script>
Before I proceed to show you how to get it done, I should explain a bit about my small plugin. This plugin accepts 2 parameters:
  • SocialSite: Name of the social site like Twitter, Facebook and Feeds (case-sensitive).
  • UName: This options holds the user name or the facebook URL or the feed reader URL or the user name.
Now it's all on the developer/designer where he wants to show the counter. I have set 3 divs on my page with ID. It is not at all necessary to use divs, you can use whatever you want. To get the counts I will do the following on the document.ready function.
$(document).ready(function () {
            $("#tweet").SocialCounter({ SocialSite: 'Twitter', UName: 'prashantmx' });
            $("#FBLikes").SocialCounter({ SocialSite: 'Facebook', UName: 'http://facebook.com/audi' });
            $("#FeedReader").SocialCounter({ SocialSite: 'Feeds', UName: 'Midnightprogrammer' });
        });

Just for your information, Feed Burner API has been deprecated by Google but they have also made sure that the current working of the feedburner would not be affected. I don't know if this is the reason behind this, but everytime I try to get my feed readers count I get 0. I think this is for time being and will be back on track soon.

Download: jquery.SocialCounter.zip (889.00 bytes)

Currently rated 4.0 by 11 people

Handling Text Changed Event In ASP.NET MVC 3 With JQuery

16. July 2011 13:00

ASP.NET MVC Jquery 

In my quest of learning MVC I came across many problems and here is one of them. I was trying to fire an event whenever a text changed event occurred. I am using JQuery to handle the text changed event but eventually the text changed event doesn't seems to be working in MVC as it is working for a text box changed event in web forms. The solution I found seems to be working fine for me as I don't want to fire an event on every key press.

To get started fire Visual Studio and create a new MVC 3 application with RAZOR view engine. I have build a simple contact manager application which allows the user to create a new contact, edit and delete existing contacts. While creating a new contact, what I want is when the user enters the e-mail address of the contact I want to make an AJAX call, which then call the method in the controller and return the HtmlString which will then show the Gravatar on the webpage.

Here is the default view of the index view. I will ask the user to enter some very basic information like name, address, email and phone.

Now, when the user enters the email address of the contact and press TAB key to move to another field or just click somewhere else on the page, the focus on the text field will be changed and the controller function then returns HtmlString to show the Gravatar image.

Here is the markup of the Create View (Create.cshtml):

@model TextChangedMVC.Models.Contacts
@{
    ViewBag.Title = "Create";
}
<h2>
    Create</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Contacts</legend>
        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Address)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Address)
            @Html.ValidationMessageFor(model => model.Address)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Email)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Email)
            <div id="Gravatar">
            </div>
            @Html.ValidationMessageFor(model => model.Email)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Phone)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Phone)
            @Html.ValidationMessageFor(model => model.Phone)
        </div>
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>

Check the highlighted code in the above markup where I have a DIV called Gravatar. This is where I will display the Gravatar of the person. Remember, when the user enters the email address we need to make sure that the Gravatar of the person displays without being an obstruction to the user, so an AJAX request to the controller will help in achieving this.

Below is the Jquery which will call the controller method called Avatar which accepts email as a parameter of string type.

<script type="text/javascript">
    $('#Email').change(function () {
        $('#Gravatar').html('');
        var selection = $('#Email').val();
        if (selection.length > 0) {
            $.post("/Home/Avatar", { email: selection },
        function (data) {
            $('#Gravatar').html(data)
        })
        }
    });
</script>

The above script is simple and here I am calling the controller's Avatar method which returns an HtmlString. At line 6, we are making a request and calling the controller's method. At line 8, the data (which is a HTML) returned will be set on the DIV called Gravatar (the placeholder for the Gravatar image).

The controller method Avatar is as follows:

public HtmlString Avatar(string email)
{
      return Gravatar.GetHtml(email, defaultImage: "http://midnightprogrammer.net/pics/default.gif");
}

Gravatar is a method is a part of the Microsoft Web Helpers. You can use web helpers by downloading it via NuGet. Check it out here if you miss my blog post on how to use Microsoft Web Helpers in MVC.

Related Post:

Currently rated 3.4 by 9 people

Prepare Your Site For IE9 With Pinify

14. May 2011 23:10

Jquery Microsoft Windows 

This is great stuff. If you own a website or a blog you should use this excellent feature of pinning fav links of your site on user's Windows 7 taskbar. Though this feature of IE9 was on hype since it's beta realease. Now it's time to use this feature for my blog. But before you start grab the latest stable version of the Pinify (formerly know as IE9ify) from Codeplex.
 
About Pinify
This plugin is written in jQuery and is hosted on Codeplex. I highly recommend you to follow this project on Codeplex. This plugin is not just about pinning, but also allows the user to customize the skin of the browser, adds a jumplist of your favourite links to the taskbar, overlay icons, tasks and thumbbar buttons. This is a total different user experience for the users /readers of your blog or site.

Preparing your site for the new experience
By now you have downloaded the latest release of the pinify from Codeplex. Open your site in Visual Studio and get to the head section. Fire the below NuGet command to install the Pinify plugin.
 
For the simplest implementation of this plugin, use the below script in the head section of your page.
<script src="Scripts/jquery-1.5.2.js" type="text/javascript"></script>
<script src="Scripts/jquery.pinify.js" type="text/javascript"></script>

<script type="text/javascript">
$().ready(function () {
     $('head').pinify();
});
</script>
Hit F5 and make sure you have selected IE9 as your default browser. After you see your site home page in the browser hit F12 to get the IE9 developer window. Under HTML tab expand the Head tree and you will come to see few meta tags.
Drag and drop the tab to your task bar. This time a new IE window will open but with a difference. Check out below, the navigation buttons has a different color, the site has an icon also.
In the above screenshot you can see the default IE icon because I have not set the favicon for my site. Once I set the fav icon in the head section of my page, I will then have a new favicon to show off. Same is with the navigation buttons, here what you are seeing is the default color, you can set your own like yellow or red or some other different color which matches the theme of your site.
 
Let's take a bit more complicate example. Now I want to do the same for my blog. For the moment I will have the following in the jumplist.
  • Archives - Link to my blog archive.
  • Twitter
  • Facebook and
  • Contact Me
The icon will be the same as my current favicon. To implement pinify for my blog I do all the work in master page which is site.master in my case. Copy and paste the below script in the head section of your page. Change the text and links accordingly.
<script src="Scripts/jquery-1.5.2.js" type="text/javascript"></script>
<script src="Scripts/jquery.pinify.js" type="text/javascript"></script>
<script type="text/javascript">
        $().ready(function () {
            $('head').pinify({
                applicationName: 'Midnight Programmer',
                tooltip: 'Programming For Fun',
                tasks: [{
                    'name': 'Archive',
                    'action': 'http://midnightprogrammer.net/archive.aspx',
                    'icon': 'favicon.ico'
                },
                {
                    'name': 'Twitter',
                    'action': 'http://twitter.com/prashantmx',
                    'icon': 'twitter.ico'
                },
                {
                    'name': 'Facebook',
                    'action': 'http://facebook.com/khandelwal.p',
                    'icon': 'facebook.ico'
                },
                {
                    'name': 'Contact Me',
                    'action': 'http://www.midnightprogrammer.net/contact.aspx',
                    'icon': 'favicon.ico'
                }]
            });
        });
</script>

After adding the script drag the tab to the taskbar and right-click it to view the task list.  

There are many other things which you can do with this plugin. I have just showed a simplest way to get you jump started with pinify. As you are reading this post try dragging the tab on your windows taskbar and right-click to see the task list as shown above.

Check out this video at Channel 9 by Brandon Satrom creator of pinify.

There are many things which can be done with pinify. To know more read the below links.

 No Rating