<div id="uploadErrors" style="color: red;"></div>
This topic explains how to process and save upload files as either file or memory streams. A detailed procedure is provided on saving files as memory stream by individual processing of each uploaded file chunk.
The following topics are prerequisites to understanding this topic:
This topic contains the following sections:
When uploading files, you typically want to process them on the server. For example, you may want to save them to a database or to compress them before saving them to a file system.
The WebUpload control can work without any application settings explicitly defined. However, best practice is to always configure things like:
A folder for storing temporary files
This can be configure to save the file to an alternate folder. Left unconfigered, the files are stored in the default location; <project folder>\Uploads .
The file size limit
The maximum allowed size for the uploading files is set through the maxFileSizeLimit
property. The default setting is 4 Mb.
The file saving mode
The file saving mode specifies how file processing is done – as a file stream or memory stream. (For details, refer to File Processing Overview.) The file saving mode is managed by the FileSaveType
property whose allowed values are filestream and memorystream corresponding to the respective manners of file processing. The default setting is filestream .
In the ASPX page, you have to implement the method which will process each individual chunk of data of the file.
Following are the general conceptual steps for WebUpload save file as stream functionality.
1. Adding WebUpload control to the page
2. (Optional) Configuring WebUpload application settings
3. Implementing the file caching functionality
4. Handling WebUpload events
The WebUpload control provides the following ways to process uploaded files depending on whether files are processed on demand while uploading, or after they are saved to a temporary file on the server:
File stream processing – the uploaded files are first saved as temporary files by the WebUpload control. Once saved, you can process the files. Use this mode when you want to save the files on the server file system.
Memory stream processing – the uploaded files can be processed on demand either during the upload (and then saved) or after they are uploaded to memory. Use this mode when you need a finer control over the upload process, (When you want, for instance, to compress the file before saving it to a disk or a database.)
File stream mode uploads the file to a temporary location (indicated by fileUploadPath
application setting) and keeps it there unless you choose to process it. In order to process the uploaded file, you need to handle UploadFinishing
event. UploadFinishing
event has a parameter of type FilesStream
which gives you access to the uploaded file. Using this parameter you can, for example, move the file to another location. When processing the file manually, you must set the UploadFinishingEventArgs.Cancel
property to true . This ensures that the temporary file will be deleted by Web Upload .)
If UploadFinishing
event is not handled, then the temporary file is renamed using its original name overwriting any existing file with the same name and stays in the temporary folder.
When using memory stream processing, files are uploaded to MemoryStream
objects that you can process manually. The WebUpload component offers the following approaches to uploading to MemoryStream
objects (depending on which events you are handling and how you process those events.):
(Recommended) Process each chunk individually.
In order to be able to process file manually, you need to handle the FileUploading
event. The FileUploading ’s FileUploadingEventArgs
parameter has a FileChunk
property of type byte array. (This property stores the current/last uploaded chunk of data.) FileUploading
is a cancelable event so you can use it to return feedback to the WebUpload control, regardless of the file chunk having been processed or not. Whether or not you choose to cancel the event, depends on if you want to process the file chunks automatically or manually.
Manual processing of the file chunks
If you want to process the file chunks manually, you need to cancel the FileUploading
event. In such cases, the WebUpload will not append the chunk into an internal MemoryStream
object. This approach is covered in detail in Saving Files as Memory Stream by Processing Each Uploaded Chunk of the File Individually – Procedure)
Automatic processing of the file chunks
If you decide not to cancel FileUploading
event, then the file chunk is appended to a MemoryStream
object which will be available in the UploadFinishing
event (UploadFinishingEventArgs.FileStream
).
To handle the FileUploading
event, use the AddFileUploadingEventHandler
method of the UploadProgressManager
class. UploadProgressManager
is a singleton class an instance of which can be accessed by its Instance
property .
Processing the whole file at once.
This is achieved by handling the UploadFinishing
event. The UploadFinishing ’s UploadFinishingEventArgs
parameter has a FileStream
property which holds the uploaded file as a MemoryStream
object. Use this property (UploadFinishingEventArgs.FileStream
) to process the file data.
This example configures WebUpload control using memory stream processing by handling the FileUploading
event and processing each file chunk individually. Uploaded chunks are appended to an ASP.NET cache buffer. When the buffer reaches a certain threshold it is written to a file on disk. This strategy allows us to optimize WebUpload usage of RAM and thus handles more simultaneous file uploads.
This example creates a custom class in order to implement file caching functionality. UploadUtils
is static class the purpose which is to handle currently uploading files into a MemoryStream
dictionary in the cache. It also uses WebUpload ’s fileUploadPath application setting in order to write files to this directory.
Optionally, a folder for storing temporary files is created and the maximum size of the uploading files is set to 100 Mb.
Following are the general requirements for saving a file as memory stream by processing each uploaded chunk of the file individually.
Microsoft® Visual Studio® 2010 or later
ASP.NET Framework
Infragistics Ignite UI® 13.1 or higher
A C# ASP.NET Web Application Microsoft Visual Studio project called “WebUploadSaveFileAsStreamExample”
The following scripts added to the Master Page
A <project folder>\Uploads folder where the temporary files will be uploaded
Following is a conceptual overview of the process:
1. Adding WebUpload control to an ASPX page
2. (Optional) Configuring WebUpload application settings
3. Implementing the file caching functionality
4. Handling WebUpload events
5. Verifing the result
The following steps demonstrate how to upload file as memory stream.
1. Open the Default.aspx page in design view
2. From the Toolbox expand the section “ASP.NET 13.1 CLR 4.0”
3. Drag and drop WebScriptManager control to the page.
4. Drag and drop WebUpload control to the page
A dialog “ ImportDefaultStyleSet ” may appear to inform you that the JavaScript and CSS files required by the control will be imported to the ig_ui directory. Press OK.
5. Add a div element which will show WebUpload errors.
We will show WebUpload errors in a div element. Add the following code after the WebUpload control code:
In HTML:
<div id="uploadErrors" style="color: red;"></div>
6. Add ig_ui directory to the solution
Enable “Show All Files” – in the Solution Explorer window press the “Show All Files” button. You can now see the ig_ui directory.
Right click on ig_ui directory and click “Include In Project” – the whole directory will be included in the project.
7. Add WebUpload script references to the Master Page
Add style references
Open Site.Master
file
Add the following style references to the Site.Master
file.
In HTML:
<link href="ig_ui/css/structure/infragistics.css" rel="stylesheet" type="text/css" />
<link href="ig_ui/css/themes/infragistics/infragistics.theme.css" rel="stylesheet" type="text/css" />
Add script references
Open Site.Master
file
Add the following script references to the Site.Master
file after the jQuery and jQuery UI scripts:
In HTML:
<script src="ig_ui/js/infragistics.js" type="text/javascript"></script>
8. (Optional) Build the site and run it
Right now you should have a working project; build and run it. Try to upload a file and see if it is in the Uploads folder.
If there is a problem you should check the browser error console for errors.
1. (Optional) Configure a temporary files folder.
The following code configures a folder for storing temporary files called Uploads .
In XML:
<appSettings>
<add key="fileUploadPath" value="~/Uploads" />
</appSettings>
2. (Optional) Configure the file size limit.
The following code sets the maximum size of the files uploading files to 100 Mb.
In XML:
<appSettings>
<!--100 Mb = 2097152 bytes-->
<add key="maxFileSizeLimit" value="104857600" />
</appSettings>
3. Configure the file saving mode.
The following code sets the file saving mode to memorystream .
In XML:
<appSettings>
<add key="FileSaveType" value="memorystream"/>
</appSettings>
To implement the caching functionality:
1. Configure the buffer size.
Open the web.config file.
Add the buffer size application setting.
In this example, the uploadUtilsBufferSize
application setting configures the threshold for buffering file data before writing it to disk. Use this configuration setting to implement our own buffering of the file in the ASP.NET cache. The following code configures it to 2 Mb.
In XML:
<appSettings>
<!--2 Mb = 2097152 bytes-->
<add key="uploadUtilsBufferSize" value="2097152" />
</appSettings>
2. Add the UploadUtils
file to the project.
Right-click on the project.
From the context menu, select Add and then Class…”. The Add New Item dialog opens.
In the Add New Item dialog, Name field, type UploadUtils.cs
.
Press Add. The file is now added to the project.
3. Implement the UploadUtils
class.
Open the UploadUtils.cs file . All the code in the steps that follow is written in that file.
Make the class static.
Add the static
keyword to the UploadUtils
class definition:
In C#:
public static class UploadUtils
{
// Class definition here see steps 2 to 7
}
Add the using
clauses.
The using
clauses are needed by the ConfigurationManager
and Path
classes. In the following code the first using clause is for the ConfigurationManager
class and the second is for the Path
class:
In C#:
using System.Configuration;
using System.IO;
Configure the constants.
The constants are necessary when the web.config file does not contain application definitions for the uploadUtilsBufferSize and fileUploadPath settings.
In C#:
//4 Mb default buffer size
private const int DEFAULT_BUFFER_SIZE = 4 * 1024 * 1024;
private const string DEFAULT_UPLOAD_PATH = "~/Uploads";
Configure the buffer size.
Define the static BufferSize
property. This property returns the uploadUtilsBufferSize application setting.
In C#:
public static int BufferSize
{
get
{
int bufferSize;
if (Int32.TryParse(ConfigurationManager.AppSettings ["uploadUtilsBufferSize"], out bufferSize))
{
return bufferSize;
}
return DEFAULT_BUFFER_SIZE;
}
}
Configure the upload path. Add the following code which defines the static UploadPath
property. This property returns the fileUploadPath application setting.
In C#:
public static string UploadPath
{
get
{
string path = DEFAULT_UPLOAD_PATH;
if (ConfigurationManager.AppSettings["fileUploadPath"] != null)
{
path = ConfigurationManager.AppSettings["fileUploadPath"];
}
if (path.StartsWith("~"))
{
path = HttpContext.Current.Server.MapPath(path);
}
if (!path.EndsWith(Path.DirectorySeparatorChar.ToString()))
path += Path.DirectorySeparatorChar;
if (!Directory.Exists(path))
throw new DirectoryNotFoundException(path);
return path;
}
}
Configure the method for retrieving the stream from the cache.
Define the GetStreamFromCache
static method. This static method returns the MemoryStream
by a given key. To do this it uses a Dictionary<string, MemoryStream>
object into the ASP.NET cache. While the file is uploading part of its data is kept for a while in this dictionary. When a threshold is reached (the one defined in UploadUtils.BufferSize
) this data chunk is appended to the file data on the disk. As you are going to see in the Handle WebUpload events section, that will make it possible not to keep the whole file into the cache. Instead, it will write the data to the file on disk by chunks which size is defined by the UploadUtils.BufferSize
property.
In C#:
public static MemoryStream GetStreamFromCache(string key)
{
Dictionary<string, MemoryStream> uploadingFiles = HttpContext.Current.Cache["UploadingFiles"] as Dictionary<string, MemoryStream>;
MemoryStream stream;
if (uploadingFiles == null)
{
uploadingFiles = new Dictionary<string, MemoryStream>();
HttpContext.Current.Cache["UploadingFiles"] = uploadingFiles;
}
if (!uploadingFiles.ContainsKey(key))
{
stream = new MemoryStream();
uploadingFiles.Add(key, stream);
}
else
{
stream = uploadingFiles[key];
}
return stream;
}
Configure the method for removing the stream from the cache.
Define the RemoveStreamFromCache
static method. This method uses a key to removes an item form the dictionary. As you are going to see in the Handle WebUpload events section, you will use it to remove the file from the currently uploading files cache.
In C#:
public static void RemoveStreamFromCache(string key)
{
Dictionary<string, MemoryStream> uploadingFiles = HttpContext.Current.Cache["UploadingFiles"] as Dictionary<string, MemoryStream>;
if (uploadingFiles != null && uploadingFiles.ContainsKey(key))
{
uploadingFiles.Remove(key);
}
}
Configure the method to write the stream to a file.
Define the AppendStreamToFile
static method. This static method writes a MemoryStream
object to a file. The method accepts as parameters a file name and the MemoryStream
value.
In C#:
public static void AppendStreamToFile(string fileName, MemoryStream stream)
{
using (FileStream fs = new FileStream(fileName, FileMode.Append))
{
stream.WriteTo(fs);
}
}
1. Client side events
Add OnError
handler
Open “Default.aspx” file
Select the WebUpload1 control
Open the Properties window (Use F4 key)
Expand the “ Client Events ” node
Double click in field on the right of OnError field (Alternatively you can select the drop down button and choose the “Add new handler…” option.)
Confirm the dialog – a dialog “Add new client side event handler pops up. Press OK to confirm it.
Implement OnError
handler
In JavaScript:
function WebUpload1_OnError(eventArgs, infoObject) {
if (infoObject.errorType === "serverside")
$("#uploadErrors").append("<p>" + infoObject.serverMessage + "</p>");
else
$("#uploadErrors").append("<p>" + infoObject.errorMessage + "</p>");
}
This OnError
client side handler appends the errors to a div with id uploadErrors which we defined earlier.
There are two types of errors server-side and client-side, which can be distinguished by the infoObject.errorType
property.
If infoObject.errorType
== “
then the error originated in developer code on the server. The error message is retained in serverside
”infoObject.serverMessage
.
If infoObject.errorType
== “
then the error originated on the client side. Its message is kept in clientside
”infoObject.errorMessage
. For more information see the Using Client- Side Events topic.
2. Server side events
Add using clauses to Default.aspx.cs file
In C#:
using System.IO;
using Infragistics.Web.UI.EditorControls;
They are used by the MemoryStream
class and UploadStatus
enum respectively.
Add FileUploading
handler
Open “Default.aspx” file
Select the WebUpload1 control
Open the Properties window (Use F4 key)
Open the Events tab by clicking the Events button
Double click in field on the right of FileUploading field.
Implement FileUploading
handler
In C#:
protected void WebUpload1_FileUploading(object sender, Infragistics.Web.UI.EditorControls.FileUploadingEventArgs e)
{
MemoryStream stream = UploadUtils.GetStreamFromCache(e.TemporaryFileName);
stream.Write(e.FileChunk, 0, e.FileChunk.Length);
if (stream.Length >= UploadUtils.BufferSize)
{
string fileName = UploadUtils.UploadPath + e.TemporaryFileName;
stream.Flush();
UploadUtils.AppendStreamToFile(fileName, stream);
stream.Close();
UploadUtils.RemoveStreamFromCache(e.TemporaryFileName);
}
e.Cancel = true;
}
The purpose of the FileUploading
event is to allow developer to manually handle the data upload when FileSaveType application setting is set to memorystream . For this purpose FileUploadingEventArgs
class contains a FileChunk
property which holds the uploaded chunk of data as a byte array.
It is very important to note that several files can be uploaded at one time; consequently, this event can rise asynchronously for the files. That is why you should employ a method of recognizing which file the incoming data is coming. One approach is to look into FileUploadingEventArgs.TemporaryFileName
property which guarantees a unique name for a file. In the FileUploading
handler we use TemporaryFileName
as a key to write file data to the ASP.NET cache by using the UploadUtils.GetStreamFromCache
static method.
Our FileUploading
handler also writes the file data to a file if the stream length exceeds the UploadUtils.BufferSize
threshold. This way we ensure that the computer RAM is utilized.
Add FileFinishing
handler
Repeat the steps from section B in order to define FileFinishing
handler
Implement FileFinishing
handler
In C#:
protected void WebUpload1_UploadFinishing(object sender, Infragistics.Web.UI.EditorControls.UploadFinishingEventArgs e)
{
string uploadFilePath = UploadUtils.UploadPath;
string fileName = UploadUtils.UploadPath + e.TemporaryFileName;
MemoryStream stream = UploadUtils.GetStreamFromCache(e.TemporaryFileName);
UploadUtils.AppendStreamToFile(fileName, stream);
stream.Close();
UploadUtils.RemoveStreamFromCache(e.TemporaryFileName);
string newFileName = UploadUtils.UploadPath + e.FileName;
if (System.IO.File.Exists(newFileName))
System.IO.File.Delete(newFileName);
System.IO.File.Move(fileName, newFileName);
}
The UploadFinishing
handler writes the last chunk of the file which is still in the cache and renames the file to its original name. If there is an existing file in the same directory it is deleted and the new file is written.
Add FileFinished
handler
Repeat the steps from section B in order to define FileFinished
handler
Implement FileFinished
handler
In C#:
protected void WebUpload1_UploadFinished(object sender, Infragistics.Web.UI.EditorControls.UploadFinishedEventArgs e)
{
switch (e.FileStatus)
{
case UploadStatus.CancelledByClientCommand:
case UploadStatus.CancelledByClientConnection:
// delete the file if the upload was unsuccessful
System.IO.File.Delete(e.TemporaryFileName);
break;
}
}
We implement UploadFinished
scenarios in order to handler situations when user cancels the upload. This implementation deletes the temporary file in which we store file data.
To verify the result, build and run the project . Upload a file and check if it is available in the temporary uploaded files folder.