Tuesday 4 October 2011

Walkthrough example with NeatUpload and ASP.NET WebForms application

In my previous post I covered the minimum sample for running the plugin with an ASP.NET MVC3 application and now through this post I’ll use an ASP.NET application with WebForms. 
The source code for this code is available from here.
Setting up
Create an Empty ASP.NET Web Application by File | New Project | ASP.NET Empty Web Application. I have chosen “WebApplicationNeatUpload” as application name. Add the plugin .js file that you can download from here, in the folder “~/Scripts/” that I recommend to create for keep the things organized, but you are free for put it wherever you consider convenient. It’s also necessary to include the jquery core library you can go to (http://jquery.com for download it).
Add Reference to the Brettle.Web.NeatUpload.dll file and the appropriated modifications to the root web.config file as mentioned in previous post. For example, the section configuration/system.webServer for my sample application contains this (In the sample I use IISExpress and it reads the configuration from that section, if you use the traditional WebDev you should change this as indicated in the previous post):
<modules runAllManagedModulesForAllRequests="true">
    <add name="UploadHttpModule" type="Brettle.Web.NeatUpload.UploadHttpModule, Brettle.Web.NeatUpload" preCondition="managedHandler"/>
</modules>
<security>
    <requestFiltering>
        <requestLimits maxAllowedContentLength="1000000000"/>
    </requestFiltering>
</security>

One last thing we have to use from original project (NeatUpload) is the file (ProgressJsonHandler.ashx) which can be found in the example I attach with this post. The propose of this file is provide an entry point for call the library methods that store in session the current file progress information and of course the default path in the plugin is that, nevertheless you can call them manually for catch that information but that’s out the scope of this post. I’ll cover more detailed information of the module in further posts.
Starting with the code
Now let’s create a new WebForm, I named Default.aspx, in code behind we are going to add a Page_Load with the following line:

protected void Page_Load(object sender, EventArgs e)
{
    uploadaction.Value = ResolveClientUrl("~/StaticUploadFile.ashx");
}

This is just for set the value to the hidden field which stores the url for the handler that will receive the post data. And in the markup view let’s do something like this:
In the head section
<script src="Scripts/jquery-1.5.1.min.js" type="text/javascript"></script>
<script src="Scripts/jquery.neatupload.js" type="text/javascript"></script>
<script type="text/javascript" defer="defer">
    $(function () {
        $("#file1").neatupload({
            postDataUrl: $("input[type=hidden][id=uploadaction]").val(),
            fnShowStatus: function (plugin, index, data) {
                $('span#progress-file').text(data.PercentComplete + "%");
            }
        });
    });
</script>

And in the body section
<form id="form1" runat="server">
<div>
    <asp:HiddenField runat="server" ID="uploadaction" />
    <div>
        <label for="newfield">
            Select File:
        </label>
        <div id="file1">
            place holder for the input -> file for upload
        </div>
    </div>
    <div>
        <span id="progress-file"></span>
    </div>
    <div>
        <input type="submit" value="save" />
    </div>
</div>
</form>

There are some elements to clarify. The scripts to include, the first is the version 1.5.1 minified of the jquery library and the second is the jquery.neatupload.js plugin, it’s important the order because any jquery plugin must load after the jquery core. The $("#file1") refers to any element with an id equals to file1 (for jquery syntax go to jquery.com). The text inside the div with id = file1 is just for be sure the plugin is running properly, so you can remove it.
In this case the only options set are postDataUrl and fnShowStatus, the remaining options use the defaults defined by the plugin.
The postDataUrl option define the url that will handle the post on the server which is stored in a hidden field, the result of ResolveClientUrl("~/StaticUploadFile.ashx"); give us the resolved route for the Action StaticUploadFile.ashx handler in the project, the important note here is the strategy of not setting this value hardcoded in JavaScript code block but store it somewhere and by JavaScript code retrieve it. If we ignore this we can get a maintenance issue caused by refactoring or name changes in the files or moving from one folder to another.

The function fnShowStatus allows to the user to execute custom code each time the progress changes, this function takes three parameters: plugin, index, and data. The plugin parameter is a reference to the object container and through plugin.options object we can access to the options either defaults or custom values set by the plugin’s user. The index is the unique identifier auto generated by the plugin at time of being inserted in the hidden queue; this value may be used to establish a correspondence between the hidden form and the visual elements. The data parameter holds a JSON returned by the handler that is polled by intervals, this JSON has multiple properties but the most important is PercentComplete which give us the percent value (0 - 100) and may be used for display to the user.
The label refers to newfield because this is the name that the input takes when it’s generated. Due to security issues the input must be moved away when the user clicks the add button, and a new one is created for replace it, the best option would be change the value by code but it’s impossible, so the name is always the same.
If we run the example at this point, nothing important are going to happen but the view is rendered and we can see the form (styles and CSS are out of this post, just basic HTML) with the two links mentioned before.
What happen on the server?
Someone must receive the data posted by hidden forms when the user clicks add and then upload. Since we are using WebForms approach, in my opinion, the easier way of perform this is using a Generic Handler (.ashx); however, you can choose a classic handler or even a Page. I made it with a Generic Handler so the code is the following:

<%@ WebHandler Language="C#" Class="WebApplicationNeatUpload.StaticUploadFile" %>
using System;
using System.Collections.Generic;
using System.Web;
using Brettle.Web.NeatUpload;

namespace WebApplicationNeatUpload
{
    public class StaticUploadFile : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            try
            {
                var tempPath = context.Server.MapPath("~/_temp_upload/");
                var value = string.Empty;
                for (var i = 0; i < UploadModule.Files.Count; i++)
                {
                    value = UploadModule.Files[i].FileName;
                    UploadModule.Files[i].SaveAs(tempPath + value);
                }
                context.Response.Write(value);
            }
            catch (Exception)
            {
                context.Response.Write("<h1>Error</h1>");
            }
        }

        public bool IsReusable
        {
            get
            {
                return true;
            }
        }
    }
}

This handler is responsible for receive the post data through the context parameter. In the example we don’t do anything complex (it’s just sample) but to copy the uploaded content to a file with the same name in the hardcoded path “~/_temp_upload/” and return the name of the last file uploaded. Here, I am going to make a key point, due to the concrete implementation of the plugin in the client, the submits are made one by one, so there won’t be more than one file per upload, but it’s important to know that NeatUpload module is capable of handling more than one file per request.
The class UploadModule is our face for retrieve the uploaded content through the Files collection and the SaveAs method allows us to save in a particular path. At this point you are able to make whatever you want with the uploaded content, save to disk, create records in database or even start complex mechanisms that process these files like video encoding.
In the next post I’ll show more different plugin configurations and examples.

Sunday 2 October 2011

Walkthrough example with NeatUpload and ASP.NET MVC 3

Through this post I’ll use an ASP.NET MVC 3 application but everything I show is possible using WebForms or whatever you want to use, let’s start. The source code for this code is available from here.
Setting up
Create an Empty ASP.NET MVC 3 Application by File | New Project | ASP.NET MVC 3 Application | Empty. I have chosen “MvcApplicationNeatUpload” as application name. Add the plugin .js file that you can download from here, in the folder “~/Scripts/” that comes with the project template or where you consider convenient.

Add Reference to the Brettle.Web.NeatUpload.dll file and the appropriated modifications to the root web.config file as mentioned in previous post. For example, the section configuration/system.webServer for my sample application contains this (In the sample I use IISExpress and it reads the configuration from that section, if you use the traditional WebDev you should change this as indicated in the previous post):

<modules runAllManagedModulesForAllRequests="true">
    <add name="UploadHttpModule" type="Brettle.Web.NeatUpload.UploadHttpModule, Brettle.Web.NeatUpload" preCondition="managedHandler"/>
</modules>
<security>
    <requestFiltering>
        <requestLimits maxAllowedContentLength="1000000000"/>
    </requestFiltering>
</security>

One last thing we have to use from original project (NeatUpload) is the file (ProgressJsonHandler.ashx) which can be found in the example I attach with this post. The propose of this file is provide an entry point for call the library methods that store in session the current file progress information and of course the default path in the plugin is that, nevertheless you can call them manually for catch that information but that’s out the scope of this post. I’ll cover more detailed information of the module in further posts.
Starting with the code
I assumed that you were using the jquery core files that come with the new project template; otherwise you can download it from (http://jquery.com). Now let’s create a controller and its corresponding view, for instance I have created the HomeController and the Index view.
This is the initial code for HomeController (~/Controllers /HomeController.cs):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Brettle.Web.NeatUpload;

namespace MvcApplicationNeatUpload.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    }
}

The controller doesn’t have yet anything relevant; it’s just an entry point for display the Index view. And code for the Index View (~/Views/Home/Index.cshtml):

@{
    ViewBag.Title = "Index";
}
<h2>Index</h2>
<script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.neatupload.js")" type="text/javascript"></script>
<script type="text/javascript" defer="defer">
    $(function() {
        $("#file1").neatupload({
            postDataUrl: $("input[type=hidden][id=upload-action]").val(),
            fnShowStatus: function (plugin, index, data) {
                $('span#progress-file').text(data.PercentComplete + "%");
            }
        });
    });
</script>

@using(Html.BeginForm("UploadFile", "Home"))
{
    @Html.Hidden("upload-action", Url.Action("UploadFile"))
    <div>
        @Html.Label("newfield", "Select File: ")
        <div id="file1">
            place holder for the input -> file for upload
        </div>
    </div>
    <div>
        <span id="progress-file"></span>
    </div>
    <div>
        <input type="submit" value="save"/>
    </div>
}
In the case of the view, there are some elements to clarify. The scripts to include, the first is the version 1.5.1 minified of the jquery library (which comes by default with ASP.NET MVC 3) and the second is the jquery.neatupload.js plugin, it’s important the order because any jquery plugin must load after the jquery core. The $("#file1") refers to any element with an id equals to file1 (for jquery syntax go to jquery.com). The text inside the div with id = file1 is just for be sure the plugin is running properly, so you can remove it.

In this case the only options set are postDataUrl and fnShowStatus, the remaining options use the defaults defined by the plugin.
The postDataUrl option define the url that will handle the post on the server which is stored in a hidden field, the result of Url.Action("UploadFile") give us the resolved route for the Action UploadFile in the HomeController, the important note here is the strategy of not setting this value hardcoded in JavaScript code block but store it somewhere and by JavaScript code retrieve it. If we ignore this we can get a maintenance issue caused by refactoring or name changes in the actions or controllers.

The function fnShowStatus allows to the user to execute custom code each time the progress changes, this function takes three parameters: plugin, index, and data. The plugin parameter is a reference to the object container and through plugin.options object we can access to the options either defaults or custom values set by the plugin’s user. The index is the unique identifier auto generated by the plugin at time of being inserted in the hidden queue; this value may be used to establish a correspondence between the hidden form and the visual elements. The data parameter holds a JSON returned by the handler that is polled by intervals, this JSON has multiple properties but the most important is PercentComplete which give us the percent value (0 - 100) and may be used for display to the user.
The label refers to newfield because this is the name that the input takes when it’s generated. Due to security issues the input must be moved away when the user clicks the add button, and a new one is created for replace it, the best option would be change the value by code but it’s impossible, so the name is always the same.
If we run the example at this point, nothing important are going to happen but the view is rendered and we can see the form (styles and CSS are out of this post, just basic HTML) with the two links mentioned before.
What happen on the server?
Someone must receive the data posted by hidden forms when the user clicks add and then upload. Since we are using MVC the most appropriated place for this task is a Controller; however, you can choose a classic handler either a .ashx file or a class that implements IHttpHandler directly or even a Page. But back to reality, we are using MVC so let’s go to the HomeController and add the following action:


[HttpPost]
public ActionResult UploadFile(FormCollection collection)
{
      var tempPath = Server.MapPath("~/_temp_upload/");
      var value = string.Empty;
      for (var i = 0; i < UploadModule.Files.Count; i++)
      {
            value = UploadModule.Files[i].FileName;
            UploadModule.Files[i].SaveAs(tempPath + value);
      }
 
      return Content(value);
}

This action is responsible for receive the post data through the parameter collection and it’s annotated with [HttpPost] attribute for indicating that only is possible to execute this method if the request is a POST from a form. In the example we don’t do anything complex (it’s just sample) but to copy the uploaded content to a file with the same name in the hardcoded path “~/_temp_upload/” and return the name of the last file uploaded. Here, I am going to make a key point, due to the concrete implementation of the plugin in the client, the submits are made one by one, so there won’t be more than one file per upload, but it’s important to know that NeatUpload module is capable of handling more than one file per request.

The class UploadModule is our face for retrieve the uploaded content through the Files collection and the SaveAs method allows us to save in a particular path. At this point you are able to make whatever you want with the uploaded content, save to disk, create records in database or even start complex mechanisms that process these files like video encoding.
In the next post I’ll show more different plugin configurations and examples.

Upload large files to the server and keep visual feedback

In my last projects I had to implement a view for upload big files (video files for playing later) and at same time keep visual feedback of the upload progress (depending on the connection speed the upload process can last from a few minutes to hours). After hours of asking to google and to many others sites in internet I concluded the following: for the server side the recommended solution was NeatUpload which is open source and solves the problem in many ways for ASP.NET, the flash solution was discarded quickly (I hate flash, it’s something personal) and it depends on the browser and plugin stuff that finally it’s a mess for the final clients, I was looking for a solution that only involves HTML, JavaScript and server components.
The only thing missing was the JavaScript client and integrating with jQuery. Sad news for finding a plugin that integrates with this solution on the server, there were many jquery uploaders but none of them were able to talk with the server the way I had implemented.
The solution: Using NeatUpload and write a jQuery plugin.

The NeatUpload™ASP.NET component allows developers to stream uploaded files to storage and allows users to monitor upload progress and it is open source. It’s a great solution for those sites that makes intense use of uploading large files (videos, large photos, etc.).
This library offers a lot of ways for integrating it with your application, for example: web controls, httpModule, flash utility, and JavaScript functionality for include in a static HTML file. I think is a good idea also integrating it with the popular jQuery library.

That’s why I wrote a plugin for integrating it with my web application and also some way make easier for the followers of this approach.

Setup NeatUpload with ASP.NET
First of all, let’s see how to use the Brettle.Web.NeatUpload .NET file uploading module, can be found at http://neatupload.codeplex.com/ for setup properly the server side. Just a quick start instructions for use it (extracted from the documentation):

·         Download the file (Brettle.Web.NeatUpload.dll) from the link above.
·         For IIS 6:
  1. Add the line below to the configuration/system.web/httpModules section of your Web.config<add name="UploadHttpModule" type="Brettle.Web.NeatUpload.UploadHttpModule, Brettle.Web.NeatUpload" />
  2. (Optional) To allow larger uploads than the default of 4 Mbytes under Microsoft's ASP.NET, you might need to add or modify the following element in your Web.config under configuration/system.web: <httpRuntime maxRequestLength="size_in_kbytes" />
·         For IIS 7+ (Integrated mode)
  1. Add the line below to the configuration/system.webServer/modules section of your Web.config to support IIS7's Integrated Pipeline Mode. <add name="UploadHttpModule" type="Brettle.Web.NeatUpload.UploadHttpModule, Brettle.Web.NeatUpload" preCondition="managedHandler"/>
  2. (Optional) To allow larger uploads than the 30MB default used by IIS7, add the following to your Web.config under the configuration/system.webServer/security/requestFiltering section: <requestLimits maxAllowedContentLength="size_in_bytes"></requestLimits>
What about the plugin?
Once properly configured the module (if you have any trouble installing it, see http://www.brettle.com/neatupload), we can start with the sample for use it in a plain HTML page and JavaScript.

The propose of this plugin is to encapsulate all dirty stuff related to sending posts to the server, and the user just tell to the plugin which page is going to handle the request in the server and who is going to return the json with the status information. The idea in general terms doesn’t differ so much from the solution found in the research, but I think is a good practical solution. The plugin allows to choose a file and has two buttons (this is fully configurable and I’ll talk about this in further posts) add and upload.
The add button moves the file selected by the user to a “queue” at bottom of the page inside an invisible div with an id auto generated that contains a form and an iframe linked and configured when the form makes the post, the result is displayed in the iframe, but the user doesn’t see nothing of that, the plugin by default also display a div contiguous to the input that contains a cancel link and the filename which also has the same id auto generated for link visual an non visual elements (this is also fully configurable by the plugin’s user).

The upload button starts the “upload engine” which consists in a loop while exists at least one file pending, it coordinates the hidden forms and commands one by one doing submit and in the other hand it’s responsible of set the timers that go to the server and retrieve the status information (copy percent, but is also possible get the copy speed and even the remaining time), the engine is also in charge of removing the group form-iframe once each finished and notifies to the client via callback functions set up in the plugin constructor, it’s also possible to modify all the appearance by implementing these callback functions and writing custom HTML or even a cute jquery-ui progress bar.
In the next post I’ll show you an example step by step with the minimum things necessary for use the NeatUpload and of course the plugin, download here.