Create custom Temp File Appender for AsyncUpload
Environment
Product | RadAsyncUpload for ASP.NET AJAX |
Description
Create custom Temp File Appender for AsyncUpload by using Reflection that will access the internal properties and invoke the instance constructors.
This approach can be used to change the chunk sizes that are appended at once when uploading large files, thus, improving the Input/output Operations per Second (IOPS).
Solution
This scenario requires the following:
Custom Temp File Appender
At first, create a class that will implement the ITempFileAppender
interface. Here you can change the buffer size (chunk size) to append at once when uploading the files.
using System.IO;
using Telerik.Web.UI.AsyncUpload;
public class CustomTempFileAppender : ITempFileAppender
{
private readonly Stream _content;
private const int MaxRetries = 10;
public static long ContentLength { get; set; }
public long AppendedContentLength
{
get
{
return ContentLength;
}
}
public CustomTempFileAppender() { }
public CustomTempFileAppender(Stream stream)
{
_content = stream;
}
public void AppendTo(string fullPath)
{
AppendToFile(fullPath, _content);
}
private void AppendToFile(string fullPath, Stream content, int retries = 1)
{
try
{
using (FileStream stream = new FileStream(fullPath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
{
using (content)
{
ContentLength = (stream.Length + content.Length);
int kiloByte = 1024; // 1KB
int megaByte = 1000 * kiloByte; // 1MB
int bufferSize = 4 * kiloByte; // 4KB chunks (Recommended for most cases)
bufferSize = megaByte; // 1MB chunks (increase the buffer size if necessary)
content.CopyTo(stream, bufferSize);
}
}
}
catch (IOException ex)
{
if (retries < MaxRetries)
{
AppendToFile(fullPath, content, retries + 1);
return;
}
throw ex;
}
}
}
Custom Upload Handler
To activate the Custom Temp File Appender, you will also need to create a Custom Upload Handler and use it for the AsyncUpload.
In the Class constructor of the Custom Upload Handler you can access the AsyncUploadHandler Type instance, the instance properties and change their values to use the new Custom Temp File Appender.
using System;
using System.Web;
using Telerik.Web.UI;
using Telerik.Web.UI.AsyncUpload;
public class CustomAsyncUploadHandler : AsyncUploadHandler
{
public CustomAsyncUploadHandler() : base()
{
System.Reflection.Assembly a = System.Reflection.Assembly.Load("Telerik.Web.UI");
Type t = a.GetType("Telerik.Web.UI.AsyncUpload.RequestData");
System.Reflection.ConstructorInfo ctorInfo = t.GetConstructors()[1];
IRequestData requestData = (IRequestData) ctorInfo.Invoke(new object[] { HttpContext.Current });
ITempFileAppender tempFileAppender = new CustomTempFileAppender(requestData.UploadedFile.InputStream);
this.GetType().GetProperty("FileAppender", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(this, tempFileAppender);
this.GetType().GetProperty("RequestData", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).SetValue(this, requestData);
}
public CustomAsyncUploadHandler(IRequestData requestData, IResponseWriter responseWriter, ITempFileAppender fileAppender) : base(requestData, responseWriter, new CustomTempFileAppender(requestData.UploadedFile.InputStream))
{
}
}