Flajaxian File Uploader 2.0

How to use FileUploader

Flajaxian FileUploader is free and open source .NET web control designed for asynchronous file upload of multiple files at the same time, without a page post back and with a progress bar indicating the current upload progress. This control does not require full trust environment. The control can be extended with the addition of server side and client side functions. Flajaxian FileUploader uses Adobe Flash Player 9 or higher Flash Player for the file upload request.

Version 2.0 can be used inside an update panel and can have the request as post back.

In order to install the control you need to follow these steps:

  1. Place com.flajaxian.FileUploader.dll in the /BIN folder of your web server
  2. Add the following tag at the top of your aspx page:
      <%@ Register TagPrefix="fjx" Namespace="com.flajaxian" Assembly="com.flajaxian.FileUploader" %>
  3. Add the following tags inside the Form element inside the BODY tag of the ASPX page, where you would like to see the FileUploader
    <fjx:FileUploader ID="FileUploader1" runat="server" >
        <Adapters>
            <fjx:FileSaverAdapter Runat="server" FolderName="UploadFolder" />
        </Adapters>
    </fjx:FileUploader>

    As you can see here we use FileSaverAdapter. The files will be uploaded on a folder with name "UploadFolder".

Request Limitations

There are several request limitations applied by the IIS. You may want to redefine the values in web.config file for the request timeout and maximum file size. You can do that in the section configuration/system.web as follow:

<httpRuntime executionTimeout="1800" 
              maxRequestLength="1048576" 
              useFullyQualifiedRedirectUrl="false" />

In this case we set timeout to 1800 seconds or 30 minutes and file size to 1048576KB or 1GB

Even more secure way would be to change that setting only for the page that owns FileUploader, for example:

<location path="Page.aspx">
    <system.web>
        <httpRuntime executionTimeout="1800" 
              maxRequestLength="1048576" 
              useFullyQualifiedRedirectUrl="false" />
    </system.web>
</location> 

IIS 7 also has a limit request filtering by default set to a little less than 30MB. The description of that can be found at the msdn site.

To override it you have to change configuration/system.webServer/security/requestFiltering/requestLimits configuration.

To set it to 1GB use:
<system.webServer> 
    <security> 
        <requestFiltering> 
            <requestLimits maxAllowedContentLength="1073741824"/> 
        </requestFiltering> 
    </security> 
</system.webServer>

If you have the default settings, after that you will get an error The requested page cannot be accessed because the related configuration data for the page is invalid and this is because by default modifications to that config section are not allowed. To change that you will need access to the %windir%\System32\inetsrv\config\applicationHost.config file where you would change section name="requestFiltering" to have overrideModeDefault="Allow" as shown here:

<section name="requestFiltering" overrideModeDefault="Allow" />

You have to also be aware that as a consequence of that change because the stream is in-memory during the upload the IIS process may recycle because of the memoryLimit attribute in the processModel tag in the Machine.config as described on the Microsoft Support Site. So you may have to change that too.

Flash Debug Player Cookies/Session Bug

Flash debug player for Firefox has a bug of not transferring the cookies with the upload request.

In order to overcome the bug you need to add the following code to your Global.asax code behind file:

public override void Init()
{
    base.Init();
    this.BeginRequest += new EventHandler(OnBeginRequest);
}
void OnBeginRequest(object sender, EventArgs e)
{
    com.flajaxian.FileUploader.RegisterAspCookies();
}

This will register the cookies

Using Different Buttons

You can specify different than the default buttons. In the source of the project in images folder you can find alternative buttons. Here is a setup with those buttons:

<fjx:FileUploader ID="FileUploader1" runat="server" 
    Width="205"
    Height="40"
    ImagesPath="~/images/UploadButtons/" 
    BrowseButtonUrl="Browse.gif"
    BrowseButtonOverUrl="BrowseOver.gif" 
    BrowseButtonPressedUrl="BrowsePress.gif"
    BrowseButtonDisabledUrl="BrowseDisabled.gif"
    UploadButtonUrl="Upload.gif"
    UploadButtonOverUrl="UploadOver.gif"
    UploadButtonPressedUrl="UploadPress.gif" 
    UploadButtonDisabledUrl="UploadDisabled.gif"
    CancelButtonUrl="Cancel.gif"
    CancelButtonOverUrl="CancelOver.gif"
    CancelButtonPressedUrl="CancelPress.gif"
    BrowseButtonX="24"
    BrowseButtonY="15"
    BrowseButtonWidth="70"
    BrowseButtonHeight="24"
    UploadButtonX="93"
    UploadButtonY="15"
    UploadButtonWidth="70"
    UploadButtonHeight="24"
    CancelButtonX="162"
    CancelButtonY="15"
    CancelButtonWidth="70"
    CancelButtonHeight="24"
    ProgressBarX="24"
    ProgressBarY="1"
    ProgressBarWidth="202"
    ProgressBarHeight="11"
    >
</fjx:FileUploader>

If you want to use different language you would create different buttons and pass their file locations and positions as in the example above.

Transparent Background

To make flash transparent set the TransparentBackground property to true. You should set this property also if you are overlaying the control with other divs.

<fjx:FileUploader ID="FileUploader1" TransparentBackground="true" runat="server" >
    <Adapters>
        <fjx:FileSaverAdapter Runat="server" FolderName="UploadFolder" />
    </Adapters>
</fjx:FileUploader>

Styles ( CSS ) of the File List Box

To change the styles of the file list box add the CssUrl property and set it with the path of a CSS file. Like this:

<fjx:FileUploader ID="FileUploader1" CssUrl="~/css/FileUploader.css" runat="server" >
    <Adapters>
        <fjx:FileSaverAdapter Runat="server" FolderName="UploadFolder" />
    </Adapters>
</fjx:FileUploader>

Then create that file and add there the default CSS. Modify the CSS according to what you want. This is the default css:

.Flajaxian_FileBox
{
    font-family:Arial,Verdana,sans-serif;
    font-size:12px;
    z-index:900;
    position:absolute;
    left:0px;
    top:0px;
    background-color:White;
    display:none;
}
.Flajaxian_FileBoxHeader
{
    width:250px;
    height:16px;
    border:solid 1px #C8C8C8;
}
.Flajaxian_FileBoxHeaderText
{
    float:right;
    width:230px;
    text-align:center
}
.Flajaxian_FileBoxHeaderArrowHolder
{
    float:left;
    width:16px;
    cursor:pointer;
}
.Flajaxian_FileBoxFileList
{
    width:250px;
    height:200px;
    overflow:auto;
    border-left:solid 1px #C8C8C8;
    border-right:solid 1px #C8C8C8;
    border-bottom:solid 1px #C8C8C8;
}
.Flajaxian_FileBoxFileListRow
{
    float:left;
    width:230px;
    padding-left:2px;
    text-align:left;
}
.Flajaxian_FileBoxFileListRow:hover
{
    background-color:#FFC;    
}
.Flajaxian_FileBoxFileListRowError
{
    float:left;
    width:230px;
    padding-left:2px;
    background-color:#F66;
    text-align:left;
}
.Flajaxian_FileBoxFileListRowUploading
{
    float:left;
    width:230px;
    padding-left:2px;
    background-color:#FFC;
    text-align:left;
}
.Flajaxian_FileBoxFileListRowUploaded
{
    float:left;
    width:230px;
    padding-left:2px;
    color:#999;
    text-align:left;
}
.Flajaxian_FileBoxFileListRowCloseBtn
{
    float:left;
    width:16px;
    padding-right:2px;
    cursor:pointer;
}

Server Side Adapters

Server side adapters are designed to extend the functionality of the Flajaxian FileUploader web control. The control comes with two adapters:

  1. FileSaverAdapter - used for saving the files in a folder on the server. Here is an example of how you can use it:
    <fjx:FileUploader ID="FileUploader1" runat="server" >
        <Adapters>
            <fjx:FileSaverAdapter Runat="server" FolderName="UploadFolder" />
        </Adapters>
    </fjx:FileUploader>

    In this example file will be uploaded on the folder UploadFolder

  2. ThumbGeneratorAdapter - used to generate thumbnails for the image files. Here is an example of how you can use it:
    <fjx:FileUploader ID="FileUploader1" runat="server" >
        <Adapters>
            <fjx:ThumbGeneratorAdapter Runat="server" 
                Extensions="jpg;jpeg" FolderName="UploadFolder" 
                Suffix="_thumb" MaximumWidth="200" MaximumHeight="200" />
        </Adapters>
    </fjx:FileUploader>

    In this example the templates will be generated in a folder UploadFolder with suffix _thumb for the files with extension jpeg or jpg. The thumbnails will be within the frame of 200 pixels height and width.

    You can use more than one adapter. They will be executed in the order of their definition. For example:

    <fjx:FileUploader ID="FileUploader1" runat="server" >
        <Adapters>
            <fjx:FileSaverAdapter Runat="server" FolderName="UploadFolder" />
            <fjx:ThumbGeneratorAdapter Runat="server" 
                Extensions="jpg;jpeg" FolderName="UploadFolder" 
                Suffix="_thumb" MaximumWidth="200" MaximumHeight="200" />
        </Adapters>
    </fjx:FileUploader>

Custom Adapters

You can create your own adapter. They must extend com.flajaxian.FileUploaderAdapter. This is a simple template you can use to create your own server side adapter:

using System;
using System.Web;
using System.Collections;

namespace CustomNamespace
{

    public class CustomAdapter : FileUploaderAdapter
    {
        /// <param name="file">Incoming file</param>
        public override void ProcessFile(HttpPostedFile file)
        {
            // process the file here
        }

    }
}

Then inside your aspx page (at the top) register your assembly as in this example (assuming your assembly is called CustomAssembly.dll and your namespace is CustomeNamespace):

<%@ Register TagPrefix="cust" Namespace="CustomeNamespace" Assembly="CustomAssembly" %>

And inside your uploader defenition use:

<fjx:FileUploader ID="FileUploader1" runat="server">
    <Adapters>
        <cust:CustomAdapter />
    </Adapters>
</fjx:FileUploader>

Limit the File Types, Size and Number

  1. File size - To limit the size of the file allowed to upload you can change the property MaxFileSize. You can also change the default warning message. For example
    <fjx:FileUploader MaxFileSize="2MB" MaxFileSizeReachedMessage="No files bigger than {0} are allowed" runat="server" >
        <Adapters>
            <fjx:FileSaverAdapter Runat="server" FolderName="UploadFolder" />
        </Adapters>
    </fjx:FileUploader>
  2. File queue size - the same you can do for all the files in the queue.
    <fjx:FileUploader MaxFileQueueSize="10MB" MaxFileQueueSizeReachedMessage="All the files cannot be bigger than than {0}" runat="server" >
        <Adapters>
            <fjx:FileSaverAdapter Runat="server" FolderName="UploadFolder" />
        </Adapters>
    </fjx:FileUploader>
  3. File number - the number of files allowed for upload at once.
    <fjx:FileUploader MaxNumberFiles="10" MaxFileNumberReachedMessage="You can select only up to {0} files in one queue" runat="server" >
        <Adapters>
            <fjx:FileSaverAdapter Runat="server" FolderName="UploadFolder" />
        </Adapters>
    </fjx:FileUploader>
  4. File types - You can limit the allowed file types by setting the property AllowedFileTypes. If the property is not specified all the file types are allowed for upload. This is how you use this property:
    <fjx:FileUploader AllowedFileTypes="Office Documents:*.rtf;*.doc;*.xls;*.docx|Web Images (Jpeg, Gig, Png):*.jpg;*.jpeg;*.png;*.gif" runat="server" >
        <Adapters>
            <fjx:FileSaverAdapter Runat="server" FolderName="UploadFolder" />
        </Adapters>
    </fjx:FileUploader>

    In this example we have defined two groups Office Documents and Web Images (Jpeg, Gig, Png). You could also specify the MAC types after another colon as in this example:

    <fjx:FileUploader AllowedFileTypes="Image Files:*.jpg;*.jpeg;*.gif;*.png:JPEG;jp2_;GIFf;PNGf|Flash Movies:*.swf:SWFL" runat="server" >
        <Adapters>
            <fjx:FileSaverAdapter Runat="server" FolderName="UploadFolder" />
        </Adapters>
    </fjx:FileUploader>

    If you want to use colon : or vertical line | in your description you could use them as doubled. For example:

    <fjx:FileUploader AllowedFileTypes="Images:: ||*.jpg;*.jpeg;*.gif;*.png||:*.jpg;*.jpeg;*.gif;*.png" runat="server" >
        <Adapters>
            <fjx:FileSaverAdapter Runat="server" FolderName="UploadFolder" />
        </Adapters>
    </fjx:FileUploader>

Send Variables with the Files

If you want to transfer some variables together with the files, you have to use State property. For example (server-side code):

FileUploader1.State.Add("MyKey", "MyValue");

The same can be done on client side with JavaScript:

<%=FileUploader1.ClientID%>.setStateVariable("MyKey", "MyValue");

or if the code is executed when the page is loaded you can use:

<script type="text/javascript">
    function addFileUploaderState(){
        window.setTimeout(function(){
            <%= FileUploader1.ClientID %>.setStateVariable("MyKey1", "MyValue1");
            <%= FileUploader1.ClientID %>.setStateVariable("MyKey2", "MyValue2");
        }, 100);
    }
    if (window.addEventListener) window.addEventListener('onload', addFileUploaderState, false); 
    else if (window.attachEvent) window.attachEvent('onload', addFileUploaderState);
</script>

though in this case a better option would be to use server-side code.

Then in your server-side event you can access those variables from the Form collection of the Request object. For example:

  string myValue = HttpContext.Current.Request.Form["MyKey"];

Make Each Request to be a Post Back Request

You can make each request to be a post back request and to transfer all the variables of the form. By default this is turned off because this way you will increase the size of the request. You can turn it on by setting the property RequestAsPostBack as in the following example:

<fjx:FileUploader RequestAsPostBack="true" runat="server" >
    <Adapters>
        <fjx:FileSaverAdapter Runat="server" FolderName="UploadFolder" />
    </Adapters>
</fjx:FileUploader>

Using Client Side Events (JavaScript interface)

You can use JsFunc_FileStateChanged property to set a function that will serve as event listener. For example if you want show information about the uploaded files in a div with id MyDiv you can have:

 <script>
function FileStateChanged(uploader, file, httpStatus, isLast){
    Flajaxian.fileStateChanged(uploader, file, httpStatus, isLast);
    var t = Flajaxian.$("MyDiv");
    if(file.state > Flajaxian.File_Uploading){
        t.innerHTML += "bytes:"+file.bytes+" name:"+file.name+" state:"+file.state+" httpStatus:"+httpStatus+" isLast:"+isLast+"</br>";
    }
}
</script>
<div id="MyDiv"></div>
<fjx:FileUploader JsFunc_FileStateChanged="FileStateChanged" runat="server" >
    <Adapters>
        <fjx:FileSaverAdapter Runat="server" FolderName="UploadFolder" />
    </Adapters>
</fjx:FileUploader>

or to redirect user to another page after all the files are uploaded you can use:

<script>
function FileStateChanged(uploader, file, httpStatus, isLast){
    Flajaxian.fileStateChanged(uploader, file, httpStatus, isLast);
    if(file.state > Flajaxian.File_Uploading && isLast){
        document.location.href = "http://www.google.com"
    }
}
</script>
<fjx:FileUploader JsFunc_FileStateChanged="FileStateChanged" runat="server" >
    <Adapters>
        <fjx:FileSaverAdapter Runat="server" FolderName="UploadFolder" />
    </Adapters>
</fjx:FileUploader>

The properties for the JavaScript file object are:

idInteger ID of the file unique per each uploading session
bytesThe size of the file in bytes
nameThe name of the file
stateSelected = 1; Uploading = 2; Uploaded = 3; Error = 5

httpStatus is the HTTP integer status code of the request, if successful 200. isLast is flag indicating weather the file is the last in the queue.

Notify User When the Maximum Storage Quota is Reached

You can notify the client for any server event by using the http status code. For example if you want to notify user of the maximum storage quota you would use:

<script runat="server">
protected void FileNameDetermining(object sender, FileNameDeterminingEventArgs args)
{
    long bytesUsed = GetBytesUserAlreadyHasUsed();
    if(bytesUsed + args.File.ContentLength > MAX_ALLOWED_STORAGE){
      args.CancelProcessing = true;
      HttpContext.Current.Response.StatusCode = 550; 
    }
}
protected void ThumbNameDetermining(object sender, FileNameDeterminingEventArgs args)
{
    if (HttpContext.Current.Response.StatusCode > 200){ 
      args.CancelProcessing = true;
    }
}
</script>
<script>
function FileStateChanged(uploader, file, httpStatus, isLast){
    Flajaxian.fileStateChanged(uploader, file, httpStatus, isLast);
    if(httpStatus == 550){
        uploader.cancel();
        alert("You have reached the maximum allowed storage quota");
    }
}
</script>
<fjx:FileUploader ID="FileUploader1" RequestAsPostBack="true" JsFunc_FileStateChanged="FileStateChanged" IsDebug="true" runat="server">
    <Adapters>
        <fjx:FileSaverAdapter Runat="server" FolderName="UploadFolder" OnFileNameDetermining="FileNameDetermining" />
        <fjx:ThumbGeneratorAdapter Runat="server" OnFileNameDetermining="ThumbNameDetermining" MaximumWidth="200" MaximumHeight="200" />
    </Adapters>
</fjx:FileUploader>

You can use http status value between 510 and 999

Inside an Update Panel

If you plan to use the control inside an update panel you have to set the property UseInsideUpdatePanel to true. Here is an example:

<asp:UpdatePanel runat="server">
    <ContentTemplate>
    
        <fjx:FileUploader ID="FileUploader1" UseInsideUpdatePanel="true" runat="server">
            <Adapters>
                <fjx:FileSaverAdapter Runat="server" FolderName="UploadFolder" />
            </Adapters>
        </fjx:FileUploader>
    
    </ContentTemplate>
</asp:UpdatePanel>

If on the other hand you have a custom client side logic that makes the parent of the uploader invisible or reloads that parent. You can do this:

<script type="text/JavaScript">
// initialize on the page load
InitUploader();

// function called BEFORE ParentDiv is reloaded
function BeforeReload(){
  DisposeUploader();
}

// function called AFTER ParentDiv is reloaded
function AfterReload(){
  InitUploader();
}
</script>
<div id="ParentDiv">
  <fjx:FileUploader ID="FileUploader1" JsFunc_Init="InitUploader" JsFunc_Dispose="DisposeUploader" runat="server">
      <Adapters>
          <fjx:FileSaverAdapter Runat="server" FolderName="UploadFolder" />
      </Adapters>
  </fjx:FileUploader>
</div>

www.Flajaxian.com - Flajaxian © 2008