Chunk Upload in ASP.NET CORE File Upload
27 Aug 202613 minutes to read
The Uploader splits large files into small chunks and sends them to the server via AJAX. You can also pause, resume, and retry a failed chunk file.
- The chunk upload works only in asynchronous upload mode.
- This feature is available from the Essential Studio® Vol 2, 2018 release.
To enable chunk upload, set the ChunkSize property of the UploaderAsyncSettings. The value is provided in bytes.
@{
var asyncSettings = new Syncfusion.EJ2.Inputs.UploaderAsyncSettings { SaveUrl = "https://services.syncfusion.com/aspnet/production/api/FileUploader/Save", RemoveUrl = "https://services.syncfusion.com/aspnet/production/api/FileUploader/Remove", ChunkSize = 102400 };
}
<ejs-uploader id="uploadFiles" asyncSettings="@asyncSettings" autoUpload="false"></ejs-uploader>using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace EJ2CoreSampleBrowser.Controllers.TextBoxes
{
public partial class UploaderController : Controller
{
public ActionResult DefaultFunctionalities()
{
return View();
}
}
}The output is shown below.

The chunk upload functionality separates the selected files into blobs of the data or chunks. These chunks are transmitted to the server using an AJAX request.
The chunks are sent in sequential order, and the next chunk is sent only after the previous chunk is uploaded successfully. If any one of the chunks fails, the remaining chunks cannot be sent to the server.
The chunkSuccess or chunkFailure event is triggered when a chunk is sent to the server successfully or fails. If all the chunks are sent to the server successfully, the Uploader’s success event is triggered.
Chunk upload will work when the selected file size is greater than the specified chunk size. Otherwise, it uploads the file normally.
Additional configurations
To modify the chunk upload, the following options can be used.
-
RetryAfterDelay - If an error occurs while sending any chunk request from JavaScript, the operation holds for 500 milliseconds (by default), and retries the chunk upload. This can be achieved by using the asyncSettings.retryAfterDelay property. You can modify the holding time interval in milliseconds.
-
RetryCount - Specifies the number of retry actions performed when the file fails to upload. By default, the retry action is performed 3 times. If the file fails to upload continuously, the request is aborted and the Uploader failure event will trigger.
The following sample specifies the chunk upload delay as 3000 milliseconds and the retry count as 5. The failure event is triggered because a wrong saveUrl is used.
@{
var asyncSettings = new Syncfusion.EJ2.Inputs.UploaderAsyncSettings { SaveUrl = "https://services.syncfusion.com/aspnet/production/api/FileUploader/Save", RemoveUrl = "https://services.syncfusion.com/aspnet/production/api/FileUploader/Remove", ChunkSize = 102400, RetryCount = 5, RetryAfterDelay = 3000 };
}
<ejs-uploader id="uploadFiles" asyncSettings="@asyncSettings" autoUpload="false"></ejs-uploader>using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace EJ2CoreSampleBrowser.Controllers.TextBoxes
{
public partial class UploaderController : Controller
{
public ActionResult DefaultFunctionalities()
{
return View();
}
}
}Resumable upload
Resumable upload allows you to continue an upload operation after a network failure or a manual pause. You can pause and resume the upload in two ways:
- Programmatically, by calling the
pauseandresumepublic methods. - Through the UI, by clicking the pause icon shown in the upload interface after the upload begins.
The pause and resume features are available only when the chunk upload is enabled.
@{
var asyncSettings = new Syncfusion.EJ2.Inputs.UploaderAsyncSettings { SaveUrl = "https://services.syncfusion.com/aspnet/production/api/FileUploader/Save", RemoveUrl = "https://services.syncfusion.com/aspnet/production/api/FileUploader/Remove", ChunkSize = 102400 };
}
<ejs-uploader id="uploadFiles" asyncSettings="@asyncSettings" autoUpload="false"></ejs-uploader>using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace EJ2CoreSampleBrowser.Controllers.TextBoxes
{
public partial class UploaderController : Controller
{
public ActionResult DefaultFunctionalities()
{
return View();
}
}
}The output is shown below.

Cancel upload
The Uploader control allows you to cancel an uploading file. This can be achieved by clicking the cancel icon or using the cancel method. The canceling event is fired whenever the file upload request is canceled. While canceling the upload request, the partially uploaded file is removed from the server.
When the request fails, the pause icon changes to a retry icon. Clicking the retry icon resends the failed chunk request to the server, and the upload resumes from where it failed. You can retry the canceled upload request again using the retry UI or the retry method. However, if you retry after canceling, the file upload starts from the beginning.
The following example demonstrates chunk upload with cancel support.
@{
var asyncSettings = new Syncfusion.EJ2.Inputs.UploaderAsyncSettings { SaveUrl = "https://services.syncfusion.com/aspnet/production/api/FileUploader/Save", RemoveUrl = "https://services.syncfusion.com/aspnet/production/api/FileUploader/Remove", ChunkSize = 102400 };
}
<ejs-uploader id="uploadFiles" asyncSettings="@asyncSettings" autoUpload="false"></ejs-uploader>using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace EJ2CoreSampleBrowser.Controllers.TextBoxes
{
public partial class UploaderController : Controller
{
public ActionResult DefaultFunctionalities()
{
return View();
}
}
}The output is shown below.

The retry action behaves differently for chunk upload and default upload.
- Chunk upload - Retries the failed request from where it previously failed.
- Default upload - Retries the failed file upload from the beginning.
Server-side configurations
The server-side implementation depends on the application requirements and logic. The following code snippet provides the server-side logic to handle chunk upload using the Uploader control.
The
chunk-indexandtotal-chunkvalues are accessible through the form data usingRequest.Form, which retrieves these details from the incoming request.
chunk-index- Indicates the index of the current chunk being received.total-chunk- Represents the total number of chunks for the file being uploaded.
public string uploads = Path.Combine(Directory.GetCurrentDirectory(), "Uploaded Files"); // Set your desired upload directory path
public async Task<IActionResult> Save(IFormFile UploadFiles)
{
try
{
if (UploadFiles.Length > 0)
{
var fileName = UploadFiles.FileName;
// Create upload directory if it doesn't exist
if (!Directory.Exists(uploads))
{
Directory.CreateDirectory(uploads);
}
if (UploadFiles.ContentType == "application/octet-stream") //Handle chunk upload
{
// Fetch chunk-index and total-chunk from form data
var chunkIndex = Request.Form["chunk-index"];
var totalChunk = Request.Form["total-chunk"];
// Path to save the chunk files with .part extension
var tempFilePath = Path.Combine(uploads, fileName + ".part");
using (var fileStream = new FileStream(tempFilePath, chunkIndex == "0" ? FileMode.Create : FileMode.Append))
{
await UploadFiles.CopyToAsync(fileStream);
}
// If all chunks are uploaded, move the file to the final destination
if (Convert.ToInt32(chunkIndex) == Convert.ToInt32(totalChunk) - 1)
{
var finalFilePath = Path.Combine(uploads, fileName);
// Move the .part file to the final destination without the .part extension
System.IO.File.Move(tempFilePath, finalFilePath);
return Ok(new { status = "File uploaded successfully" });
}
return Ok(new { status = "Chunk uploaded successfully" });
}
else //Handle normal upload
{
var filePath = Path.Combine(uploads, fileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
await UploadFiles.CopyToAsync(fileStream);
}
return Ok(new { status = "File uploaded successfully" });
}
}
return BadRequest(new { status = "No file to upload" });
}
catch (Exception ex)
{
return StatusCode(500, new { status = "Error", message = ex.Message });
}
}
// Method to handle file removal (optional if needed)
public async Task<IActionResult> Remove(string UploadFiles)
{
try
{
var filePath = Path.Combine(uploads, UploadFiles);
if (System.IO.File.Exists(filePath))
{
System.IO.File.Delete(filePath);
return Ok(new { status = "File deleted successfully" });
}
else
{
return NotFound(new { status = "File not found" });
}
}
catch (Exception ex)
{
return StatusCode(500, new { status = "Error", message = ex.Message });
}
}Explore the ASP.NET Core File Upload feature tour page to discover its groundbreaking features. You can also check out our ASP.NET Core File Upload example to see how to browse and select files for upload to the server.