HelpBot Assistant

How can I help you?

Chunk upload in React Uploader component

21 Feb 202624 minutes to read

The Uploader sends the large file split into small chunks and transmits to the server using AJAX. You can also pause, resume, and retry the failed chunk file.

  • The chunk upload works in asynchronous upload only.
  • This feature is available from the Essential® Studio Vol 2, 2018 release.

To enable the chunk upload, set the size to chunkSize option of the upload and it receives the value in bytes.

[Class-component]

import { UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import * as ReactDOM from "react-dom";
export default class App extends React.Component {
    path = {
        chunkSize: 102400,
        // set chunk size for enable the chunk upload
        removeUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Remove',
        saveUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Save'
    };
    render() {
        return (<div className="chunkupload">
            <UploaderComponent asyncSettings={this.path}/>
      </div>);
    }
}
ReactDOM.render(<App />, document.getElementById('fileupload'));
import { UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import * as ReactDOM from "react-dom";

export default class App extends React.Component<{}, {}> {
  public path: object = {
    chunkSize: 102400,
    // set chunk size for enable the chunk upload
    removeUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Remove',
    saveUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Save'

  }
  public render(): JSX.Element {
    return (
      <div className="chunkupload">
            <UploaderComponent asyncSettings={this.path} />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('fileupload'));

[Functional-component]

import { UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import * as ReactDOM from "react-dom";
function App() {
    const path = {
        chunkSize: 102400,
        // set chunk size for enable the chunk upload
        removeUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Remove',
        saveUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Save'
    };
    return (<div className="chunkupload">
            <UploaderComponent asyncSettings={path}/>
      </div>);
}
ReactDOM.render(<App />, document.getElementById('fileupload'));
import { UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App(){
  const path: object = {
    chunkSize: 102400,
    // set chunk size for enable the chunk upload
    removeUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Remove',
    saveUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Save'

  }
    return (
      <div className="chunkupload">
            <UploaderComponent asyncSettings={path} />
      </div>
    );
  }

ReactDOM.render(<App />, document.getElementById('fileupload'));

The chunk upload functionality divides large files into smaller data chunks for transmission. Chunks are sent to the server in sequential order—each chunk must complete successfully before the next one begins, ensuring proper file reassembly on the server. If a chunk fails, subsequent chunks are not sent. The chunkSuccess or chunkFailure event fires when each chunk completes. After all chunks upload successfully, the overall success event triggers.

Chunk upload will work when the selected file size is greater than the specified chunk size. otherwise, it upload the files normally.

Additional configurations

Fine-tune chunk upload behavior using the following properties:

  • RetryAfterDelay - When a chunk request fails, the Uploader pauses for 500 milliseconds (default) before retrying. Customize this delay using the asyncSettings.retryAfterDelay property by specifying a custom interval in milliseconds.

  • RetryCount - Controls how many times the component attempts to resend a failed chunk. By default, the retryCount is set to 3. After exhausting all retries, the upload aborts and the failure event triggers.

The following sample specifies the chunk upload delay with 3000 milliseconds and the retry count is 5. The failure event is triggered as the wrong saveUrl is used.

[Class-component]

import { UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import * as ReactDOM from "react-dom";
export default class App extends React.Component {
    path = {
        // set chunk size for enable the chunk upload
        chunkSize: 102400,
        // provided the wrong url to showcase the chunk upload failure related properties.
        removeUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Remove',
        // set time delay for automatic retry when chunk upload failed
        retryAfterDelay: 3000,
        // set count for automatic retry when chunk upload failed
        retryCount: 5,
        saveUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Save'
    };
    render() {
        return (<div className="chunkupload">
        <UploaderComponent asyncSettings={this.path}/>
    </div>);
    }
}
ReactDOM.render(<App />, document.getElementById('fileupload'));
import { UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import * as ReactDOM from "react-dom";

export default class App extends React.Component<{}, {}> {
  public path: object = {
    // set chunk size for enable the chunk upload
    chunkSize: 102400,
    // provided the wrong url to showcase the chunk upload failure related properties.
    removeUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Remove',
    // set time delay for automatic retry when chunk upload failed
    retryAfterDelay: 3000,
    // set count for automatic retry when chunk upload failed
    retryCount: 5,
    saveUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Save'

  }
  public render(): JSX.Element {
    return (
    <div className="chunkupload">
        <UploaderComponent asyncSettings={this.path} />
    </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('fileupload'));

[Functional-component]

import { UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import * as ReactDOM from "react-dom";
function App() {
    const path = {
        // set chunk size for enable the chunk upload
        chunkSize: 102400,
        // provided the wrong url to showcase the chunk upload failure related properties.
        removeUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Remove',
        // set time delay for automatic retry when chunk upload failed
        retryAfterDelay: 3000,
        // set count for automatic retry when chunk upload failed
        retryCount: 5,
        saveUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Save'
    };
    return (<div className="chunkupload">
        <UploaderComponent asyncSettings={path}/>
    </div>);
}
ReactDOM.render(<App />, document.getElementById('fileupload'));
import { UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App() {
  const path: object = {
    // set chunk size for enable the chunk upload
    chunkSize: 102400,
    // provided the wrong url to showcase the chunk upload failure related properties.
    removeUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Remove',
    // set time delay for automatic retry when chunk upload failed
    retryAfterDelay: 3000,
    // set count for automatic retry when chunk upload failed
    retryCount: 5,
    saveUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Save'

  }
    return (
    <div className="chunkupload">
        <UploaderComponent asyncSettings={path} />
    </div>
    );
}

ReactDOM.render(<App />, document.getElementById('fileupload'));

Resumable upload

Resume interrupted uploads using the pause and resume methods or UI controls. This feature supports recovery from network failures or manual pauses. The pause button appears after upload begins.

Pause and resume functionality is available only when chunk upload is enabled.

[Class-component]

import { UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import * as ReactDOM from "react-dom";
export default class App extends React.Component {
    path = {
        // set chunk size for enable the chunk upload
        chunkSize: 102400,
        removeUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Remove',
        saveUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Save'
    };
    render() {
        return (<div className="chunkupload">
            <UploaderComponent asyncSettings={this.path}/>
        </div>);
    }
}
ReactDOM.render(<App />, document.getElementById('fileupload'));
import { UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import * as ReactDOM from "react-dom";

export default class App extends React.Component<{}, {}> {
  public path: object = {
    // set chunk size for enable the chunk upload
    chunkSize: 102400,
    removeUrl: 'https://ej2.syncfusion.com/services/api/uploadbox/Remove',
    saveUrl: 'https://ej2.syncfusion.com/services/api/uploadbox/Save'
  }
  public render(): JSX.Element {
    return (
        <div className="chunkupload">
            <UploaderComponent asyncSettings={this.path} />
        </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('fileupload'));

[Functional-component]

import { UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import * as ReactDOM from "react-dom";
function App() {
    const path = {
        // set chunk size for enable the chunk upload
        chunkSize: 102400,
        removeUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Remove',
        saveUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Save'
    };
    return (<div className="chunkupload">
            <UploaderComponent asyncSettings={path}/>
        </div>);
}
ReactDOM.render(<App />, document.getElementById('fileupload'));
import { UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App(){
  const path: object = {
    // set chunk size for enable the chunk upload
    chunkSize: 102400,
    removeUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Remove',
    saveUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Save'
  }
    return (
        <div className="chunkupload">
            <UploaderComponent asyncSettings={path} />
        </div>
    );
}

ReactDOM.render(<App />, document.getElementById('fileupload'));

Cancel upload

The uploader component allows you to cancel the uploading file. This can be achieved by clicking the cancel icon or using the cancel method. The canceling event will be 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 is changed to retry icon. By clicking the retry icon, sends the failed chunk request again to the server and upload started from where it is failed. You can retry the canceled upload request again using retry UI or retry methods. But, if you retry this, the file upload action again starts from initial.

The following example explains about chunk upload with cancel support.

[Class-component]

import { UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import * as ReactDOM from "react-dom";
export default class App extends React.Component {
    path = {
        // set chunk size for enable the chunk upload
        chunkSize: 102400,
        removeUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Remove',
        saveUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Save'
    };
    render() {
        return (<div className="chunkupload">
        <UploaderComponent asyncSettings={this.path}/>
      </div>);
    }
}
ReactDOM.render(<App />, document.getElementById('fileupload'));
import { UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import * as ReactDOM from "react-dom";

export default class App extends React.Component<{}, {}> {
  public path: object = {
    // set chunk size for enable the chunk upload
    chunkSize: 102400,
    removeUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Remove',
    saveUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Save'
  }
public render(): JSX.Element {
    return (
      <div className="chunkupload">
        <UploaderComponent asyncSettings={this.path} />
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('fileupload'));

[Functional-component]

import { UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import * as ReactDOM from "react-dom";
function App() {
    const path = {
        // set chunk size for enable the chunk upload
        chunkSize: 102400,
        removeUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Remove',
        saveUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Save'
    };
    return (<div className="chunkupload">
        <UploaderComponent asyncSettings={path}/>
      </div>);
}
ReactDOM.render(<App />, document.getElementById('fileupload'));
import { UploaderComponent } from '@syncfusion/ej2-react-inputs';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App() {
  const path: object = {
    // set chunk size for enable the chunk upload
    chunkSize: 102400,
    removeUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Remove',
    saveUrl: 'https://services.syncfusion.com/react/production/api/FileUploader/Save'
  }
    return (
      <div className="chunkupload">
        <UploaderComponent asyncSettings={path} />
      </div>
    );
}

ReactDOM.render(<App />, document.getElementById('fileupload'));

The retry action has different working behavior for chunk upload and default upload.

  • Chunk upload - Retries to upload the failed request where it is failed previously.
  • Default upload - Retries to upload the failed file again from initial.

Server-Side configurations

The server-side implementation entirely depends on the application requirements and logic. The following code snippet provides the server-side logic to handle the chunk upload using the uploader components.

The chunk-index and total-chunk values are accessible through the form data using Request.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 });
    }
}

You can also explore React File Upload feature tour page for its groundbreaking features. You can also explore our React File Upload example to understand how to browse the files which you want to upload to the server.