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
.
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:
XFRequest.ResumeInfo.Resumable
property should be set to true
.XFRequest.ResumeInfo.CacheRequest
property should be set to
true
or false
depending on whether or not you want a complete
copy of the file cached on the client. In a resumable upload, XFileEE stores upload
data in a temporary directory on the client, before starting the upload. XFileEE's
ResumeInfo.CacheRequest
property allows you to specify whether XFileEE
should cache the whole request - including the files to upload - or just store information
about the upload. Caching the whole request guarantees the integrity of the request
data when an upload is resumed. This may be useful if you suspect that the file
to be uploaded could be edited between the time the upload fails and the time at
which it is resumed. Setting CacheRequest
to true will ensure that
the file is resumed in its original state, as it will be resumed from the cache
instead of from its original location on the file system. Please note, however,
that there is a significant performance penalty for caching requests that include large
files.XFRequest.ResumeInfo.TopFolder
property should be set to the location
where XFile should store resumability information on the client.When resuming a request:
XFRequest.Resume
([XFRequest.ResumeInfo.JobID])should be used to specify which
upload request should be resumed.
<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>
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.
UseHttpModuleWithAspDotNet
should be set to "1" to enable the FileUpEE HttpModule.
Resumable
should be set
to "1" to enable resumability.
FileUpEeTempDir
should
be set to a location with adequate NTFS permissions for your web application's identity.
This is where the module will temporarily cache the upload request. In addition,
the module will temporarily store files that provide information regarding the resumability
status of the request. These files will be cleaned out of the directory if the upload
is sucessful.
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
.
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;
}
}
}
}