title | page_title | description | slug | tags | published | position |
---|---|---|---|---|---|---|
How to Extend the RadAsyncUpload handler |
How to Extend the RadAsyncUpload handler - RadAsyncUpload |
Check our Web Forms article about How to Extend the RadAsyncUpload handler. |
asyncupload/how-to/how-to-extend-the-radasyncupload-handler |
how,to,extend,the,radasyncupload,handler |
true |
0 |
This article explains how to create your own file upload handler to be used through RadAsyncUpload. Such a handler allows you to implement features specific to your use case; direct storage of files to a desired location like a database; advanced security measures specific to the application like tying uploads to user session, scanning files before saving them to the disk, throttling uploads and so on.
This article contains the following sections:
tip You can find an example implementation in the following Live Demo: Custom HTTP Handler.
To create a custom handler, you must inherit the built-in AsyncUploadHandler
class and then implement the desired functionality (for example, saving images directly to a database, without using temporary folder).
-
Create the Custom Handler
-
Create a generic handler in your Web Application (for example,
myHandler.ashx
) -
Make sure the class extends the
Telerik.Web.UI.AsyncUploadHandler
class -
Override the
Process
methodpublic class CustomUploadHandler : AsyncUploadHandler { protected override IAsyncUploadResult Process(UploadedFile file, HttpContext context, IAsyncUploadConfiguration configuration, string tempFileName) { // do something here return base.Process(file, context, configuration, tempFileName); } }
Public Class CustomUploadHandler Inherits AsyncUploadHandler Protected Overrides Function Process(ByVal file As UploadedFile, ByVal context As HttpContext, ByVal configuration As IAsyncUploadConfiguration, ByVal tempFileName As String) As IAsyncUploadResult 'do something here Return MyBase.Process(file, context, configuration, tempFileName) End Function End Class
-
-
Set the path to the custom handler in the RadAsyncUpload through its
HttpHandlerUrl
property:ASPX
<telerik:RadAsyncUpload runat="server" ID="RadAsyncUpload1" HttpHandlerUrl="~/myHandler.ashx"></telerik:RadAsyncUpload>
In the Process
method, the arguments provide the following:
-
UploadedFile
is the file that is currently processed. You can use it to obtain the input stream, file name, extension and so on. -
HttpContext
is the currentHttpContext
. Since the handler implements theIRequiresSessionState
interface, theSession
object is available as well. -
Configuration
is a class that implements theIAsyncUploadConfiguration
interface and, by default, has the following properties:-
TargetFolder
—the folder where RadAsyncUpload would have saved the file if the built-in handler is used, as provided by the developer. -
TempTargetFolder
—the temporary folder where RadAsyncUpload would have stored the file before saving it to the target folder, if the built-in handler is used, as provided by the developer. -
MaxFileSize
—the maximum file size set by the developer for the RadAsyncUpload. -
TimeToLive
—the time until the file is deleted from the temporary folder if the built-in handler were used.
-
-
TempFileName
is the uploaded file's temporary name. It is used by the built-in handler for the temporary folder only.
When a custom handler is used, the temporary folder is used as follows:
-
File chunks are stored in it until the entire file is collected and passed to the
Process
method of the handler. The entire file is not saved to the temporary folder after that. -
Entire files (when chunk upload is disabled or when the file fits in a single chunk) go directly to the
Process
method of the handler and are not saved to the temporary folder. In such cases, the files are not stored to the hard disk of the server at all and remain in memory only. -
When a RadAsyncUpload instance initializes, it will write a test file (an empty file with the
RadUploadTestFile
name) to the temporary folder in itsPreRender
event. You can disable that by setting the control'sEnablePermissionsCheck
property tofalse
.
Thus, to save files, you would usually use the Process
method. If you are using the FileUploaded event
to save files, you may get an error: UploadedFiles.SaveAs Throws FileNotFound Error with Custom Handler.
The custom handler inherits the built-in handler and you can use it to customize the behavior and information. Once you have the custom handler in place, you can amend it with the following features:
- Send Custom Information to and From the Handler
- Change Cache Dependency
- Custom File Name Validation
- Accommodate Linux and MacOS File Names
The Process
method returns an interface—IAsyncUploadResult
. You can use it to transmit custom information between the client and the server. For example, a User ID or other piece of application logic.
note If you use this, see [Security - Custom Metadata]({%slug asyncupload-security%}#custom-metadata).
To return custom information to the client:
-
Create a class that implements
IAsyncUploadResult
. For example,SampleAsyncUploadResult
. -
Populate it with the
CreateDefaultUploadConfiguration<T>
method exposed by the RadAsyncUpload instance. -
Set the desired custom values.
-
Return the created object.
caption How to send information from the custom handler to the client
protected override IAsyncUploadResult Process(UploadedFile file, HttpContext context, IAsyncUploadConfiguration configuration, string tempFileName)
{
// Populate the default (base) result into an object of type SampleAsyncUploadResult
SampleAsyncUploadResult result = CreateDefaultUploadResult<SampleAsyncUploadResult>(file);
//generate the custom information in the custom field
result.CustomField = "some value";
//return the data to the client
return result;
}
Protected Overrides Function Process(file As UploadedFile, context As HttpContext, configuration As IAsyncUploadConfiguration, tempFileName As String) As IAsyncUploadResult
' Populate the default (base) result into an object of type SampleAsyncUploadResult
Dim result As SampleAsyncUploadResult = CreateDefaultUploadResult(Of SampleAsyncUploadResult)(file)
'generate the custom information in the custom field
result.CustomField = "some value"
'return the data to the client
Return result
End Function
tip You can also use this approach to send meaningful error information from the custom handler to the browser. See the How to Capture File Upload Errors with Custom Handler KB article.
Then, you can use this information on the page that was used to upload the file:
-
Subscribe to the
FileUploaded
event of the RadAsyncUpload. -
Cast the
UploadResult
property of the event arguments object to your custom class.
caption Consuming the custom information from the control event on the page
protected void RadAsyncUpload1_FileUploaded(object sender, FileUploadedEventArgs e)
{
//SampleAsyncUploadResult is the custom class
SampleAsyncUploadResult result = e.UploadResult as SampleAsyncUploadResult;
}
Protected Sub RadAsyncUpload1_FileUploaded(ByVal sender As Object, ByVal e As FileUploadedEventArgs)
'SampleAsyncUploadResult is the custom class
Dim result As SampleAsyncUploadResult = TryCast(e.UploadResult, SampleAsyncUploadResult)
End Sub
With the IAsyncUploadConfiguration
interface you can also send information to the handler. To do that:
-
create an object that implements
IAsyncUploadConfiguration
. -
Set it to the
UploadConfiguration
property of the RadAsyncUpload. You can obtain the configuration object from theCreateDefaultUploadConfiguration<T>
method provided by RadAsyncUpload.
Such an object is serialized and sent to the handler with each request.
caption How to send custom information to the handler
protected void Page_Load(object sender, EventArgs e)
{
// Populate the default (base) upload configuration into an object of type SampleAsyncUploadConfiguration
// The custom configuration class name may vary in your application
SampleAsyncUploadConfiguration config = RadAsyncUpload1.CreateDefaultUploadConfiguration<SampleAsyncUploadConfiguration>();
// Populate any additional fields
config.UserID = 1;
// The upload configuration will be available in the handler
RadAsyncUpload1.UploadConfiguration = config;
}
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
' Populate the default (base) upload configuration into an object of type SampleAsyncUploadConfiguration
' The custom configuration class name may vary in your application
Dim config As SampleAsyncUploadConfiguration = RadAsyncUpload1.CreateDefaultUploadConfiguration(Of SampleAsyncUploadConfiguration)()
' Populate any additional fields
config.UserID = 1
' The upload configuration will be available in the handler
RadAsyncUpload1.UploadConfiguration = config
End Sub
Then, in the handler, the sent information can be obtained in the following way
- Cast the
IAsyncUploadConfiguration
argument to your custom class
caption Consuming the custom information from the handler
protected override IAsyncUploadResult Process(UploadedFile file, HttpContext context, IAsyncUploadConfiguration configuration, string tempFileName)
{
int userID = -1;
// You can obtain any custom information passed from the page via casting the configuration parameter to your custom class
var sampleConfiguration = configuration as SampleAsyncUploadConfiguration;
if (sampleConfiguration != null)
{
userID = sampleConfiguration.UserID;
}
// More code here..
}
Protected Overrides Function Process(file As UploadedFile, context As HttpContext, configuration As IAsyncUploadConfiguration, tempFileName As String) As IAsyncUploadResult
Dim userID As Integer = -1
' You can obtain any custom information passed from the page via casting the configuration parameter to your custom class
Dim sampleConfiguration = TryCast(configuration, SampleAsyncUploadConfiguration)
If sampleConfiguration IsNot Nothing Then
userID = sampleConfiguration.UserID
End If
' More code here..
End Function
By default, RadAsyncUpload deletes the temporary files after some time, in case they are not saved to the target folder. You can set this time interval through the TemporaryFileExpiration
property. The default is 4
hours.
Overriding the AddCacheDependency
method allows you to modify or even remove the default temporary files removal callback. In order to leave temporary files instead of deleting them, you can store the file path in cache and leave out the CacheItemRemovedCalback
in the override of the AddCacheDependency
method.
For this to have effect, you must not override the Process
method. This is equivalent to you using the built-in handler code, but only overriding the way the cache dependency is managed. Alternatively, in the Process
override, call the base method to save the uploaded file to the temporary folder base.Process(file, context, configuration, tempFileName);
.
caption How to remove the default temporary files expiration
protected override void AddCacheDependency(HttpContext context, string tempFileName, TimeSpan timeToLive, string fullPath)
{
if (context.Cache.Get(tempFileName) == null)
{
context.Cache.Insert(tempFileName, fullPath);
// Instead of the predefined
// context.Cache.Insert(tempFileName, fullPath, null, DateTime.Now.Add(timeToLive), TimeSpan.Zero, CacheItemPriority.NotRemovable, RemovedCallback);
}
}
Protected Overrides Sub AddCacheDependency(context As HttpContext, tempFileName As String, timeToLive As TimeSpan, fullPath As String)
If context.Cache.Get(tempFileName) Is Nothing Then
context.Cache.Insert(tempFileName, fullPath)
' Instead of the predefined
' context.Cache.Insert(tempFileName, fullPath, Nothing, DateTime.Now.Add(timeToLive), TimeSpan.Zero, CacheItemPriority.NotRemovable, RemovedCallback)
End If
End Sub
By default, the CheckOriginalFileNameForInvalidChars
verifies the File Name against the Microsoft's Naming Convention.
Overriding the CheckOriginalFileNameForInvalidChars
method allows you to extend this validity check.
caption Implement custom file name validation
protected override bool CheckOriginalFileNameForInvalidChars(string originalFileName)
{
// Check if the fileName is a null value or an empty string
bool fileNameIsNullOrEmpty = string.IsNullOrEmpty(originalFileName);
// Check if the fileName contains invalid path characters
bool fileNameHasInvalidPathCharacters = originalFileName.IndexOfAny(Path.GetInvalidFileNameChars()) > -1;
// Check if the fileName contains "A" (or any other custom validation)
bool fileNameContainsA = originalFileName.IndexOf("A") > -1;
return (fileNameIsNullOrEmpty || fileNameHasInvalidPathCharacters || fileNameContainsA);
}
Protected Overrides Function CheckOriginalFileNameForInvalidChars(originalFileName As String) As Boolean
' Check if the fileName is a null value or an empty string
Dim fileNameIsNullOrEmpty As Boolean = String.IsNullOrEmpty(originalFileName)
' Check if the fileName contains invalid path characters
Dim fileNameHasInvalidPathCharacters As Boolean = originalFileName.IndexOfAny(Path.GetInvalidFileNameChars()) > -1
' Check if the fileName contains "A" (or any other custom validation)
Dim fileNameContainsA As Boolean = originalFileName.IndexOf("A") > -1
Return (fileNameIsNullOrEmpty OrElse fileNameHasInvalidPathCharacters OrElse fileNameContainsA)
End Function
On some operating systems like [MAC OS and Linux]({%slug asyncupload/how-to/how-to-upload-files-from-mac-or-linux%}), it is possible to have file names which are invalid for the Windows File System. File names may contain special characters or might not be in accordance with the Microsoft's Naming Convention.. This makes file uploading impossible for such files.
To upload a file with an invalid name, you must rename it before the uploading takes place. You can do that by overriding ChangeOriginalFileName
.
caption Change the file name to accommodate Linux and MacOS file names
protected override string ChangeOriginalFileName(string fileName)
{
//Return the current name if there is no invalid character
if (fileName.IndexOfAny(System.IO.Path.GetInvalidFileNameChars()) == -1)
{
return fileName;
}
else
{
//Escape invalid characters
fileName = Regex.Replace(fileName, @"[^\w\.@-]", "", RegexOptions.None, TimeSpan.FromSeconds(1.5));
//If all characters are invalid return underscore as a file name
if (Path.GetFileNameWithoutExtension(fileName).Length == 0)
{
return fileName.Insert(0, "_");
}
//Else return the escaped name
return fileName;
}
}
Protected Overrides Function ChangeOriginalFileName(fileName As String) As String
'Return the current name if there is no invalid character
If fileName.IndexOfAny(System.IO.Path.GetInvalidFileNameChars()) = -1 Then
Return fileName
Else
'Escape invalid characters
fileName = Regex.Replace(fileName, "[^\w\.@-]", "", RegexOptions.None, TimeSpan.FromSeconds(1.5))
'If all characters are invalid return underscore as a file name
If Path.GetFileNameWithoutExtension(fileName).Length = 0 Then
Return fileName.Insert(0, "_")
End If
'Else return the escaped name
Return fileName
End If
End Function
-
[Server-side Programming]({%slug asyncupload/server-side-programming/overview%})