A 2-Tier Resumable Upload in ASP.NET



Resumable Uploading

FileUpEE can resume failed uploads. This tutorial will demonstrate resumability between the client and webserver in ASP.NET. The code examples on this page are a simplified version of the ASP.NET two-tiered resumable upload in the FileUpEE samples.

Since browsers do not support resumable uploading, XFileEE must be used on the client to create a client-to-server resumable upload application.

In ASP.NET, resumability between the client and the server is accomplished through the HttpModule. Hence, it is necessary to use the HttpModule for every FileUpEE resumable upload using ASP.NET.

An upload may fail because of a number of reasons, including a network connection failure, or because the upload size was greater than MaxKBytesToCancel.


Client-side Configuration and Code
Client configuration

XFileEE must be used as the client for any resumable upload. Because of this, the XFileEE cab must be downloadable from your web directory.

XFileEE has resumability-specific functionality that must be added to your XFileEE upload code:

When making a resumable request:

When resuming a request:

The client code:

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Two-Tier Resumable Upload via XFile Non-Visual Control</title>

    <script type="text/javascript">


    /****************************************************************************
    **** Do Upload (XFile Non-Visual) *******************************************
    *****************************************************************************/
	 
    function send() 
    {   		    
        //--- Add the selected files for upload to the XFRequest object's Files 
        //--- collection
        XFile.AddFile(document.getElementById("File1").value, "File1");   		         
        XFile.AddFile(document.getElementById("File2").value, "File2");
        		 
        // -------------------- Resumability ------------------------------------
        // ----------------------------------------------------------------------			    
        //--- Set Resumable to True to tell XFileEE that the upload is resumable
        XFile.ResumeInfo.Resumable = true;
				    
        //--- If CacheRequest is set to True, XFile will make copies of the files 
        //--- before uploading. This is to guarantee data integrity in case the 
        //--- user modifies a file between upload attempts. 
        //--- If CacheRequest is set to false, XFile will not pre-cache the files.  
        //--- This speeds up the upload process significantly but carries a risk 
        //--- of file corruption if an upload is resumed after the user modifies 
        //--- the file.
        XFile.ResumeInfo.CacheRequest = false;
				    
        //--- Set TopFolder property to tell XFileEE where to store information 
        //--- that will allow a failed upload to be resumed.
        //--- If CacheRequest is set to true, copies of the files will be stored 
        //--- in this folder until the upload is complete.
        //--- If CacheRequest is set to false, only information about the request 
        //--- will be stored.  
        //--- Note: If TopFolder is not set, XFile will store request data in the 
        //--- user's temp directory.
        XFile.ResumeInfo.TopFolder = "C:\\Temp\\XFileResumeInfo\\";	
		            			
        // -------------------- Process Upload ----------------------------------
        // ----------------------------------------------------------------------
        
        //--- Set the URL where you will upload the files to
        XFile.CurrentUrl = 
            "http://localhost/TwoTierResumableWebServer_Docs/
                ResumableUpload/TwoTRUploadWS.uplx";
        
        try
        {
            //--- Begin the transfer
            XFile.Start();
        }
        catch(errorObject)
        {
            alert("Error: " + errorObject.message +
                    "An error has occurred during the upload. You may resume the 
                        transfer by clicking the \"Resume\" button.");
        }
    }	

    /****************************************************************************
    **** Do Resume (XFile Non-Visual) *******************************************
    *****************************************************************************/
	
    function resume() 
    { 
        try
        {
            //--- Resume the transfer by passing the JobID
            XFile.Resume(XFile.ResumeInfo.JobId);
        }
		catch(errorObject)
        {
            alert("Error: " + errorObject.message +
                    "An error has occurred during the resume. You may re-resume 
                        the transfer by clicking the \"Resume\" button.");                
        }		
    }
		
    </script>

</head>
<body>
    <h2 style="text-align: center">
        Two-Tier Resumable Upload via XFile Non-Visual Control</h2>
    <!-- This OBJECT tag declares and loads the XFRequest object (the non-visual
        control of XFile) into the page.  Change the CODEBASE attribute if you 
        choose to deploy the SAXFileEE.cab from another location -->
    <object id="XFile" codebase="/cab/SAXFileEE.cab"
        classid="clsid:8B3512EF-4FF5-4aa4-9CDE-56BB03E04B9F">
    </object>
    <br />
    <table align="center" width="600">
        <tr>
            <td>
                Description:  This sample demonstrates how to perform a 
                resumable two-tier upload to the webserver using XFile's Non-Visual 
                ActiveX Control.  After the user selects files from the HTML 
                file input controls, the files are passed to XFile programmatically 
                by calling the AddFile method.
            </td>
        </tr>
    </table>
    <form>
        <table align="center" border="0">
            <tr>
                <td align="left" valign="top">
                    <b>Enter Filename:</b></td>
                <td>
                    <input type="file" id="File1"><br />
                    <i>Click "Browse" to select a file to upload.</i>
                </td>
            </tr>
            <tr>
                <td align="left" valign="top">
                    <b>Enter Filename:</b></td>
                <td>
                    <input type="file" id="File2"><br />
                    <i>Click "Browse" to select a file to upload.</i>
                </td>
            </tr>
         </table>
    </form>
    <p align="center">
        <input id="btnUpload" onclick="send()" type="button" value="Upload" 
            name="btnUpload" style="width: 70px" />
        <input disabled id="btnResume" onclick="resume()" type="button" 
            value="Resume" name="btnResume" style="width: 70px" />
    </p>
</body>
</html>

HttpModule Settings

The FileUpEE HttpModule sits on the server and intercepts client requests that are sent to pages using the .uplx extension. In ASP.NET, it is used to enable resumable uploads. The server side code page in ASP.NET resumable uploads must have a .uplx extension for this reason.

The HttpModule is configured using appSettings within the web.config file of the application. The following keys must be changed to enable resumable file transfers in ASP.NET.


Server-Side Processing Page

FileUpEE

No special considerations must be made in the FileUpEE code for resumable uploads. The same server side code can be used for both resumable and non-resumable uploads. However, greater user control is provided when the FileUpEE(Boolean EnablePreserveResumeInfoBehavior) constructor is used.

Passing in true to FileUpEE will prevent FileUpEE from disposing of resume information until the upload transfer is confirmed to be successful. The default preserve behavior is for FileUpEE to not delete resume information until the saSaveResult for each uploaded file returns saSaved or saExists.

This behavior can be overridden by the script writer through a new property PreserveResumeInfo that has been added to the FileUpEe object. This property can be set to saPreserveBehavior.saPreserve or saPreserveBehavior.saDelete to preserve or delete the resume information when the FileUpEe object is destructed. The default setting is saPreserveBehavior.saDefault.

The webserver code:

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Web;
using System.Web.SessionState;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using SoftArtisans.Net;

namespace SoftArtisans.FileUpEESamples
{
    public class TwoTRUploadWS : System.Web.UI.Page
    {
        private void Page_Load(object sender, EventArgs e)
        {
            //--- When the page loads, process the upload
            ProcessUpload();
        }

        private void ProcessUpload()
        {
            //--- Declare the FileUpEe instance variable
            FileUpEe oFileUpEE = null;

            try
            {
                //--- Instantiate the FileUpEE object
                
                //--- Note: For resumable uploads in ASP.NET, a new constructor which 
                //--- receives  a boolean "EnablePreserveResumeInfoBehavior" parameter 
                //--- has been added to FileUpEE. Passing in "true" will prevent 
                //--- FileUpEE from disposing of resume information until the upload 
                //--- transfer is confirmed to be successful. The default preserve 
                //--- behavior is that FileUpEE will not delete resume information 
                //--- until the "saSaveResult" for each uploaded file returns "saSaved" 
                //--- or "saExists".  This behavior can be overridden by the script 
                //--- writer through a new property "PreserveResumeInfo" that has been 
                //--- added to the FileUpEe object. This  property can be set to 
                //--- "saPreserveBehavior.saPreserve" or "saPreserveBehavior.saDelete" 
                //--- to preserve or delete the resume information when the FileUpEe 
                //--- object is destructed.  The default setting is 
                //--- "saPreserveBehavior.saDefault".
                oFileUpEE = new FileUpEe(true);

                //--- Let FileUpEE know what stage we're working on
                //--- Note: Be sure to set this immediately after instantiating the object
                oFileUpEE.TransferStage = saTransferStage.saWebServer;

                //--- Set the directory on the webserver where you want to save the files
                oFileUpEE.DestinationDirectory = 
                    @"C:\Program Files\SoftArtisans\FileUpEE\temp\DestinationDir";

                //--- Call ProcessRequest to read the request from the form
                //--- Parameters for ProcessRequest:
                //---	1) Page.Request - HttpRequest instance
                //---	2) SOAP Request? - false, the web server is not being sent SOAP 
                //---      from the form
                //---	3) Auto Process? - false, do not auto process on the web server
                //---	Note: false, false is typically what you will use in a web server 
                //---   script
                oFileUpEE.ProcessRequest(Request, false, false);

                //--- Loop through all of the files in the Files collection
                foreach (FileEe oFile in oFileUpEE.Files)
                {
                    //--- If a file was submitted, show the results
                    //--- FileEe.Size will be 0 if no file was submitted
                    if (oFile.Size != 0)
                    {
                        //--- Save the file to the webserver disk
                        oFile.Save();

                    }
                }
            }
            catch (SaProcessRequestException ex)
            {
                //--- In your error handling code you can override the preserve behavior 
                //--- if you choose to preserve or delete resume information
                //oFileUpEE.PreserveResumeInfo = saPreserveBehavior.saPreserve; 
                //oFileUpEE.PreserveResumeInfo = saPreserveBehavior.saDelete;

                Response.StatusCode = 500;
                Page.Response.Write("<B>WebServer ProcessRequest exception:</B>  "
                    + ex.Message);
            }
            catch (Exception ex)
            {
                //--- In your error handling code you can override the preserve behavior 
                //--- if you choose to preserve or delete resume information
                //oFileUpEE.PreserveResumeInfo = saPreserveBehavior.saPreserve; 
                //oFileUpEE.PreserveResumeInfo = saPreserveBehavior.saDelete;

                Response.StatusCode = 500;
                Page.Response.Write("<B>WebServer exception:</B>  " + ex.Message);
            }
            finally
            {
                //--- Always call FileUpEE.Dispose in finally block
                if (oFileUpEE != null)
                    oFileUpEE.Dispose();
                oFileUpEE = null;
            }
        }
    }
}

Top

Copyright © 2010 SoftArtisans, Inc. All rights reserved.