As you know ActiveX/Java Uploader sends files and additional metadata from client computers to server side in HTTP POST requests. This approach requires server script to parse the received requests and handle uploaded data. Reading this topic you will learn to extract files and additional data sent by clients, save them all to file system on a server or handle in some other way. There are three approaches to perform this task:
If you parse requests using the ASP.NET Request object and enable sending files by chunks, you will have to write significant amount of non-trivial server-side code to assembly the files on your server. Thus, we do not recommend enabling chunks if you use this method of handling requests.
Further in this topic every approach will be described in detail. Firstly, let us describe ActiveX/Java Uploader ASP.NET components.
All the ActiveX/Java Uploader ASP.NET classes and types are located in the Aurigma.ImageUploader.dll
assembly. There are three main ones allowing to process the data uploaded from client computers (Uploader,
UploadRequest and UploadHandler).
All three of them have similar API and functionality giving flexible typed access to these data. The class to use in your application
depends on where you handle the received data:
.ashx
handler from this class and it will automatically parse requests received from ActiveX/Java Uploader
and will expose API to access the files and data.This section describes the simplest way of handling uploaded data - autosave. This approach allows you to save all the uploaded files
to the specified folder on your server without writing a lot of code. All server-side components described in the
previous section can save uploaded files automatically. You just have to choose the component,
plug it in your ASP.NET application and configure the Autosave
and the DestinationFolder properties.
To enable autosave feature set the Autosave property to true
.
After that set the DestinationFolder property to the path to folder
where uploaded files are saved. If the specified folder does not exist, ActiveX/Java Uploader will try to create it.
Also autosave supports the Uploader.FolderProcessingMode feature that allows uploading whole folders rather than just files and restoring their structure on server side automatically, see the Uploading Folders in ActiveX/Java Uploader ASP.NET topic for more information.
If you need to process the saved files in some way, then a page specified in the UploadSettings.RedirectUrl setting is the right place for this. Just put your code there and it will be executed after the upload process is completed.
The following examples show how to configure autosave for each of the server-side components.
After embedding the Uploader control in your page as it is described in the Quick Start with ActiveX/Java Uploader ASP.NET topic, configure the control like it is shown below:
<aur:Uploader ID="Uploader1" runat="server" AutoSave="true" DestinationFolder="~/Catalog" />
This control is configured in the same manner as Uploader. Additionally you have to configure the UploadSettings.ActionUrl property, set it to a URL to a page where the UploadRequest control is hosted (both absolute and relative URLs are supported), as it is shown here:
<aur:Uploader runat="server"> <UploadSettings ActionUrl="UploadRequestPage.aspx" /> </aur:Uploader>
Since UploadHandler is not a WebForms control you
do not have to create a separate page to host it. You just create a new handler (an .ashx
file), which inherits
from the UploadHandler. For example, like this one:
public class SimpleHandler : Aurigma.ImageUploader.UploadHandler { public SimpleHandler () { DestinationFolder = "~/Catalog"; AutoSave = true; } }
And specify a URL to this handler as a value of the UploadSettings.ActionUrl property (both absolute and relative URLs are supported).
If your file storage is located separately from your Web site (for example, on another disk or server), it is recommended to additionally specify the TempDirectory property which configures a temporary folder where ASP.NET server-side part of ActiveX/Java Uploader saves files before moving them to the DestinationFolder. Thus, TempDirectory should be located at the same disk where you store files.
ActiveX/Java Uploader prepares files on client side in the way set by so-called converters. Each converter specifies
what to do with a file selected for upload: upload it as is or apply some transformation before upload (resize image down, extract and send icon
associated with a file, or compress a file to ZIP format). Converters
(except for SourceFile
one) add suffixes to file names uploaded to a server. For example, the
name.ext_Thumbnail0.ext
filename is the result of applying Mode="*.*=Thumbnail"
converter on name.ext
file. For a full list of possible suffixes see the ConvertedFile.Name property description.
Filenames collisions may occur while saving uploaded files to a destination folder.
If the destination folder already has a file with the same name as uploaded one,
the uploaded file will be saved under its name appended by _xx
, where xx
is a number
starting from 2
. For example, if there is a file with the name name.ext
in the destination folder and a user tries
to upload another file with the same name then uploaded file is saved as name_02.ext
file. If
name_02.ext
file exists as well then the recently uploaded file gets name_03.ext
filename and so on.
This approach requires quite a bit of code, however, this method is more flexible than autosave described before. The main idea is to handle uploaded files and data in the FileUploaded and/or AllFilesUploaded event handlers of the mentioned before server-side components. The first event fires each time a user-specified file is successfully uploaded. The second event fires when the whole upload session completes and all the files, metadata, and additional data are received on the server side. It means that the first event fires as many times as number of files selected for upload, whereas the second one fires only once.
Now, when you understand the differences between these events, let us discuss how to create these event handlers. There are two steps to this process:
Before creating an event handler you have to select server-side component to use. If you do not know the differences between them, please, read the server-side components section of this article.
To add FileUploaded and/or AllFilesUploaded event handler for the Uploader control just specify event name in the control events list or add OnFileUploaded and/or OnAllFilesUploaded parameters declaratively. The following example creates both event handlers for the Uploader control.
<aur:Uploader ID="Uploader1" runat="server" OnFileUploaded="FileUploaded" OnAllFilesUploaded="AllFilesUploaded" />
The page code-behind should contain these event handlers with the specified names:
protected void FileUploaded(object sender, Aurigma.ImageUploader.FileUploadedEventArgs e) { // Your code } protected void AllFilesUploaded(object sender, Aurigma.ImageUploader.AllFilesUploadedEventArgs e) { // Your code }
The UploadRequest event handlers can be created in the same way as analogous Uploader event handlers described above. There is the only difference - in case of using UploadRequest you have to set the UploadSettings.ActionUrl property to the page containing the UploadRequest instance.
There is the example of event handler below.
When using the UploadHandler you have to create a new class
derived from the UploadHandler class and add events handlers to this new class.
In the following example the SimpleHandler class (contained in the SimpleHandler.ashx
file) is this new derived class.
public class SimpleHandler : Aurigma.ImageUploader.UploadHandler { public SimpleHandler() { FileUploaded += OnFileUploaded; AllFilesUploaded += OnAllFilesUploaded; } public void OnFileUploaded(object sender, Aurigma.ImageUploader.FileUploadedEventArgs e) { // put your code here... } public void OnAllFilesUploaded(object sender, Aurigma.ImageUploader.AllFilesUploadedEventArgs e) { // put your code here... } }
Then implement these handlers, for instance, like it is shown in the example below.
And, finally, set the UploadSettings.ActionUrl property:
<aur:Uploader runat="server"> <UploadSettings ActionUrl="SimpleHandler.ashx" /> </aur:Uploader>
After creating a skeleton event handler you have to write its implementation. You can accomplish any operation on the uploaded data using ActiveX/Java Uploader ASP.NET types and classes. For example, not just save all files to the same folder, but change destination depending on file type. Moreover, you can save metadata of uploaded files to your database or to an XML file which allows you to perform, for instance, various file-sorting operations. For better understanding let us separate description of the uploaded data handling into the following sections:
The ASP.NET server-side part of ActiveX/Java Uploader among its types has the UploadedFile class. This type holds all the data associated with a single file selected for upload (files prepared on client side by ActiveX/Java Uploader from the original file in accordance with converters set in the settings, additional fields, and other data). The FileUploaded and AllFilesUploaded events give access to the UploadedFile instances via arguments of their event handlers: FileUploadedEventArgs.UploadedFile and AllFilesUploadedEventArgs.UploadedFiles properties, respectively.
Now let us examine how to get access to uploaded files via the UploadedFile instances. Each UploadedFile object has associated collection of files prepared by ActiveX/Java Uploader converters on client side. Each of these files is represented by an instance of the ConvertedFile type. This way, the collection of converted files associated with a particular file selected for upload is accessible via the UploadedFile.ConvertedFiles property.
Each ConvertedFile has three main members to handle the file:
The main difference between MoveTo(String) and
SaveAs(String) methods is in the following. By the moment when the
FileUploaded or AllFilesUploaded event is fired, ASP.NET server-side part of
ActiveX/Java Uploader has already completed parsing of HTTP POST request(s) and saved files to a temporary folder which is configured
via the TempDirectory property. When you trigger the MoveTo(String) method, it moves the file from this temporary folder to the specified one.
However, when you call the SaveAs(String) method copies the file from
a temporary location to the specified folder. MoveTo(String)
method works faster when you transfer the file from a temporary location (which is in the /App_Data
folder, by default)
to a location on the same disk. That is the difference. Thus, it is recommended to select temporary folder on the same disk where your file storage is located.
All the metadata uploaded along with a file is accessible through the UploadedFile properties and can be divided into the following groups:
There is only one property in this group - UploadedFile.RelativePath which returns a relative path to the original file on the client machine. This property makes sense only if ActiveX/Java Uploader is allowed to upload folders (FolderProcessingMode has Upload value).
This group includes properties containing information about the original file:
The ConvertedFile class provides access to some additional information along with the access to the converted file. Its properties contain the following information:
This group includes the following properties:
This example is an FileUploaded event handler implementation which saves
an original file and its resized copy to the ../Gallery/
and ../Gallery/Thumbnails/
folders respectively
and writes some file-related information (filenames, image dimensions, user description, and etc.) to an XML file.
protected void FileUploaded(object sender, Aurigma.ImageUploader.FileUploadedEventArgs e) { string galleryPath = Server.MapPath("Gallery/"); string thumbnailsPath = galleryPath + "Thumbnails/"; //Save original file. //It is the first file in ConvertedFiles collection as we set first converter mode to SourceFile. string sourceFileName = GetSafeFileName(galleryPath, e.UploadedFile.SourceName); e.UploadedFile.ConvertedFiles[0].SaveAs(System.IO.Path.Combine(galleryPath, sourceFileName)); //Save thumbnail. //It is the second file in ConvertedFiles collection as we set second converter mode to Thumbnail. string thumbnailFileName = GetSafeFileName(thumbnailsPath, e.UploadedFile.SourceName); e.UploadedFile.ConvertedFiles[1].SaveAs(System.IO.Path.Combine(thumbnailsPath, thumbnailFileName)); //Save file info. System.Xml.XmlDocument descriptions = new System.Xml.XmlDocument(); if (System.IO.File.Exists(galleryPath + "Descriptions.xml")) descriptions.Load(galleryPath + "Descriptions.xml"); else descriptions.AppendChild(descriptions.CreateElement("files")); System.Xml.XmlElement file = descriptions.CreateElement("file"); file.SetAttribute("name", sourceFileName); file.SetAttribute("thumbName", thumbnailFileName); file.SetAttribute("width", Convert.ToString(e.UploadedFile.SourceWidth)); file.SetAttribute("height", Convert.ToString(e.UploadedFile.SourceHeight)); file.SetAttribute("description", e.UploadedFile.Description); descriptions.DocumentElement.AppendChild(file); //Save xml file with uploaded files info. descriptions.Save(galleryPath + "Descriptions.xml"); } private string GetSafeFileName(string path, string fileName) { // ... }
The last way of handling uploaded files is to parse the request manually via the intrinsic Request object of System.Web.HttpRequest class. Before the Page_Load method is called, ASP.NET initializes the Request object, i.e. finishes receiving HTTP POST request from a client computer and fills the Form and Files collections in. To simplify accessing the POST request fields ActiveX/Java Uploader ASP.NET provides the PostFields class.
If you choose this approach we do not recommend enabling chunks, otherwise, you will have to write significant amount of non-trivial server-side code to assembly the files on your server.
ActiveX/Java Uploader sends a HEAD request before the POST one to check if authentication is needed. So, you should check the type of Request and handle POST requests only.
The following code sample saves original files, thumbnails, and original file-related information using described approach.
private void Page_Load(System.Object sender, System.EventArgs e) { if (System.String.Equals(Request.RequestType, "POST")) { string galleryPath = Server.MapPath("Gallery/"); string thumbnailsPath = galleryPath + "Thumbnails/"; int fileCount = int.Parse(Request[PostFields.PackageFileCount]); for (int i = 0; i < fileCount; i++) { string originalFileName = Request[string.Format(PostFields.SourceName, i)]; // save original file string sourceFileName = GetSafeFileName(galleryPath, originalFileName); HttpPostedFile sourceFile = Request.Files[string.Format(PostFields.File, 0, i)]; if (sourceFile != null) sourceFile.SaveAs(System.IO.Path.Combine(galleryPath, sourceFileName)); // save thumbnail string thumbnailFileName = GetSafeFileName(thumbnailsPath, originalFileName); HttpPostedFile thumbnailFile = Request.Files[string.Format(PostFields.File, 1, i)]; if (thumbnailFile != null) thumbnailFile.SaveAs(System.IO.Path.Combine(thumbnailsPath, thumbnailFileName)); //Save file info. System.Xml.XmlDocument descriptions = new System.Xml.XmlDocument(); if (System.IO.File.Exists(galleryPath + "Descriptions.xml")) descriptions.Load(galleryPath + "Descriptions.xml"); else descriptions.AppendChild(descriptions.CreateElement("files")); System.Xml.XmlElement file = descriptions.CreateElement("file"); file.SetAttribute("name", sourceFileName); file.SetAttribute("thumbName", thumbnailFileName); file.SetAttribute("width", Request[string.Format(PostFields.SourceWidth, i)]); file.SetAttribute("height", Request[string.Format(PostFields.SourceHeight, i)]); file.SetAttribute("description", Request[string.Format(PostFields.Description, i)]); descriptions.DocumentElement.AppendChild(file); //Save xml file with uploaded files info. descriptions.Save(galleryPath + "Descriptions.xml"); } } } private string GetSafeFileName(string path, string fileName) { // ... }