New to Telerik UI for ASP.NET AJAXStart a free 30-day trial

Create custom Temp File Appender for AsyncUpload

Environment

ProductRadAsyncUpload 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.

C#
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.

C#
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))
    {
    }
}