File Attachments in EJ2 React Chat UI component

15 Dec 202524 minutes to read

The Chat UI component supports message attachments, enabling users to upload and send files (images, documents, and more) alongside messages for richer, more contextual conversations. Enable this functionality using the enableAttachments property and customize the behavior through the attachmentSettings configuration.

Enable file attachments

Enable file attachment support by setting the enableAttachments property to true. By default, it is false.

import { ChatUIComponent } from '@syncfusion/ej2-react-interactive-chat';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App() {
    const currentUserModel = {
        id: "user1",
        user: "Albert"
    };

    return (
        // specifies the tag for render the Chat UI component
        <ChatUIComponent user={currentUserModel} enableAttachments={true}></ChatUIComponent>
    );
}

ReactDOM.render(<App />, document.getElementById('container'));
import { ChatUIComponent, UserModel } from '@syncfusion/ej2-react-interactive-chat';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App() {
    const currentUserModel: UserModel = {
        id: "user1",
        user: "Albert"
    };

    return (
        // specifies the tag for render the Chat UI component
        <ChatUIComponent user={currentUserModel} enableAttachments={true}></ChatUIComponent>
    );
}

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

Configure attachment settings

Use the attachmentSettings property to customize file attachment behavior, including upload endpoints, file type restrictions, and size limits.

Setting saveUrl and removeUrl

Set the saveUrl and removeUrl properties to specify server endpoints for handling file uploads and removals. The saveUrl processes file uploads, while the removeUrl handles file deletion requests.

import { ChatUIComponent } from '@syncfusion/ej2-react-interactive-chat';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App() {
    const currentUserModel = {
        id: "user1",
        user: "Albert"
    };

    const attachmentSettings = {
      saveUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Save',
      removeUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Remove'
    };
    return (
        // specifies the tag for render the Chat UI component
        <ChatUIComponent user={currentUserModel} enableAttachments={true} attachmentSettings= {attachmentSettings} ></ChatUIComponent>
    );
}

ReactDOM.render(<App />, document.getElementById('container'));
import { ChatUIComponent, FileAttachmentSettingsModel, UserModel } from '@syncfusion/ej2-react-interactive-chat';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App() {
    const currentUserModel: UserModel = {
        id: "user1",
        user: "Albert"
    };

    const attachmentSettings: FileAttachmentSettingsModel = {
      saveUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Save',
      removeUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Remove'
    };
    return (
        // specifies the tag for render the Chat UI component
        <ChatUIComponent user={currentUserModel} enableAttachments={true} attachmentSettings= {attachmentSettings} ></ChatUIComponent>
    );
}

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

Setting file type

Use the allowedFileTypes property to specify which file types users can upload. This property accepts file extensions (e.g., ‘.pdf’, ‘.docx’) or MIME types to control the types of files that can be attached.

import { ChatUIComponent } from '@syncfusion/ej2-react-interactive-chat';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App() {
    const currentUserModel = {
        id: "user1",
        user: "Albert"
    };

    const attachmentSettings = {
      saveUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Save',
      removeUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Remove',
      allowedFileTypes: '.pdf'
    };
    return (
        // specifies the tag for render the Chat UI component
        <ChatUIComponent user={currentUserModel} enableAttachments={true} attachmentSettings= {attachmentSettings} ></ChatUIComponent>
    );
}

ReactDOM.render(<App />, document.getElementById('container'));
import { ChatUIComponent, FileAttachmentSettingsModel, UserModel } from '@syncfusion/ej2-react-interactive-chat';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App() {
    const currentUserModel: UserModel = {
        id: "user1",
        user: "Albert"
    };

    const attachmentSettings: FileAttachmentSettingsModel = {
        saveUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Save',
        removeUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Remove',
        allowedFileTypes: '.pdf'
    };
    return (
        // specifies the tag for render the Chat UI component
        <ChatUIComponent user={currentUserModel} enableAttachments={true} attachmentSettings= {attachmentSettings} ></ChatUIComponent>
    );
}

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

Setting file size

Configure the maxFileSize property to define the maximum file size allowed for uploads. Specify the size in bytes. The default value is 30000000 bytes (approximately 30 MB). Files exceeding this limit will not be uploaded.

import { ChatUIComponent } from '@syncfusion/ej2-react-interactive-chat';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App() {
    const attachmentSettings = {
      saveUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Save',
      removeUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Remove',
      maxFileSize: 4000000
    };
    const currentUserModel = {
        id: "user1",
        user: "Albert"
    };

    return (
        // specifies the tag for render the Chat UI component
        <ChatUIComponent user={currentUserModel} enableAttachments={true} attachmentSettings= {attachmentSettings} ></ChatUIComponent>
    );
}

ReactDOM.render(<App />, document.getElementById('container'));
import { ChatUIComponent, FileAttachmentSettingsModel, UserModel } from '@syncfusion/ej2-react-interactive-chat';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App() {
    const currentUserModel: UserModel = {
        id: "user1",
        user: "Albert"
    };

    const attachmentSettings: FileAttachmentSettingsModel = {
      saveUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Save',
      removeUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Remove',
      maxFileSize: 4000000
    };
    return (
        // specifies the tag for render the Chat UI component
        <ChatUIComponent user={currentUserModel} enableAttachments={true} attachmentSettings= {attachmentSettings} ></ChatUIComponent>
    );
}

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

Setting save format

Control the format used to send files to the server using the saveFormat property when path is not set. It does not change how files are uploaded. The default value is Blob.

  • Blob: Used for fast, memory‑efficient local previews.
  • Base64: Reads the file as a Base64 data URL, useful when you need an inline data URL.
import { ChatUIComponent } from '@syncfusion/ej2-react-interactive-chat';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App() {
    const currentUserModel = {
        id: "user1",
        user: "Albert"
    };

    const attachmentSettings = {
        saveUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Save',
        removeUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Remove',
        saveFormat: 'Base64'
    };
    return (
        // specifies the tag for render the Chat UI component
        <ChatUIComponent user={currentUserModel} enableAttachments={true} attachmentSettings= {attachmentSettings}></ChatUIComponent>
    );
}

ReactDOM.render(<App />, document.getElementById('container'));
import { ChatUIComponent, FileAttachmentSettingsModel, UserModel } from '@syncfusion/ej2-react-interactive-chat';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App() {
    const currentUserModel: UserModel = {
        id: "user1",
        user: "Albert"
    };

    const attachmentSettings: FileAttachmentSettingsModel = {
        saveUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Save',
        removeUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Remove',
        saveFormat: 'Base64'
    };
    return (
        // specifies the tag for render the Chat UI component
        <ChatUIComponent user={currentUserModel} enableAttachments={true} attachmentSettings= {attachmentSettings} ></ChatUIComponent>
    );
}

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

Setting server path

The path property specifies the public base URL where uploaded files are (or will be) hosted. When this property is set, it takes precedence over the value defined in saveFormat. This means that even if saveFormat includes a different location or structure for storing files, the path property will be used it for generating the file URL.

import { ChatUIComponent } from '@syncfusion/ej2-react-interactive-chat';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App() {
    const currentUserModel = {
        id: "user1",
        user: "Albert"
    };

    const attachmentSettings = {
      saveUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Save',
      removeUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Remove',
      path: 'D:/CustomPathLocation'
    };
    return (
        // specifies the tag for render the Chat UI component
        <ChatUIComponent user={currentUserModel} enableAttachments={true} attachmentSettings= {attachmentSettings} ></ChatUIComponent>
    );
}

ReactDOM.render(<App />, document.getElementById('container'));
import { ChatUIComponent, FileAttachmentSettingsModel, UserModel } from '@syncfusion/ej2-react-interactive-chat';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App() {
    const currentUserModel: UserModel = {
        id: "user1",
        user: "Albert"
    };

    const attachmentSettings: FileAttachmentSettingsModel = {
      saveUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Save',
      removeUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Remove',
      path: 'D:/CustomPathLocation'
    };
    return (
        // specifies the tag for render the Chat UI component
        <ChatUIComponent user={currentUserModel} enableAttachments={true} attachmentSettings= {attachmentSettings} ></ChatUIComponent>
    );
}

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

Enabling drag-and-drop

Toggle drag-and-drop support for attachments via enableDragAndDrop property. The default value is true.

import { ChatUIComponent } from '@syncfusion/ej2-react-interactive-chat';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App() {
    const currentUserModel = {
        id: "user1",
        user: "Albert"
    };

    const attachmentSettings = {
      saveUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Save',
      removeUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Remove',
      enableDragAndDrop: false
    };
    return (
        // specifies the tag for render the Chat UI component
        <ChatUIComponent user={currentUserModel} enableAttachments={true} attachmentSettings= {attachmentSettings} ></ChatUIComponent>
    );
}

ReactDOM.render(<App />, document.getElementById('container'));
import { ChatUIComponent, FileAttachmentSettingsModel, UserModel } from '@syncfusion/ej2-react-interactive-chat';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App() {
    const currentUserModel: UserModel = {
        id: "user1",
        user: "Albert"
    };

    const attachmentSettings: FileAttachmentSettingsModel = {
      saveUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Save',
      removeUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Remove',
      enableDragAndDrop: false
    };
    return (
        // specifies the tag for render the Chat UI component
        <ChatUIComponent user={currentUserModel} enableAttachments={true} attachmentSettings= {attachmentSettings} ></ChatUIComponent>
    );
}

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

Setting maximum count

Restrict how many files can be attached at once using maximumCount. The default value is 10. If users select more than the allowed count, the maximum count reached error will be displayed.

import { ChatUIComponent } from '@syncfusion/ej2-react-interactive-chat';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App() {
    const currentUserModel = {
        id: "user1",
        user: "Albert"
    };

    const attachmentSettings = {
      saveUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Save',
      removeUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Remove',
      maximumCount: 2
    };
    return (
        // specifies the tag for render the Chat UI component
        <ChatUIComponent user={currentUserModel} enableAttachments={true} attachmentSettings= {attachmentSettings} ></ChatUIComponent>
    );
}

ReactDOM.render(<App />, document.getElementById('container'));
import { ChatUIComponent, FileAttachmentSettingsModel, UserModel } from '@syncfusion/ej2-react-interactive-chat';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App() {
    const currentUserModel: UserModel = {
        id: "user1",
        user: "Albert"
    };

    const attachmentSettings: FileAttachmentSettingsModel = {
      saveUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Save',
      removeUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Remove',
      maximumCount: 2
    };
    return (
        // specifies the tag for render the Chat UI component
        <ChatUIComponent user={currentUserModel} enableAttachments={true} attachmentSettings= {attachmentSettings} ></ChatUIComponent>
    );
}

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

Templates

Customizing the file preview

Provide a custom UI for previewing selected files using previewTemplate. Use this to render thumbnails, filenames, progress, remove buttons, or any additional metadata prior to sending.

Customizing the attachments

Control how attachments appear inside message bubbles with attachmentTemplate. Use this to tailor the display of images, documents, or custom file types once the message is posted.

import { ChatUIComponent } from '@syncfusion/ej2-react-interactive-chat';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App() {

    // Preview Template Component
    const PreviewTemplate = (props) => {
      const file = props.selectedFile;
      const type = (file?.rawFile?.type || file?.type || '').toLowerCase();
      const isImage = type.startsWith('image/');
      const isVideo = type.startsWith('video/');
      const sizeBytes = file?.size || 0;
      const humanSize = sizeBytes < 1024
        ? `${sizeBytes} B`
        : sizeBytes < 1024 * 1024
          ? `${(sizeBytes / 1024).toFixed(1)} KB`
          : `${(sizeBytes / (1024 * 1024)).toFixed(1)} MB`;
      const ext = (file?.name?.split('.').pop() || '').toUpperCase();

      return (
        <div className="c-preview--card">
          <div className="c-preview-card">
            <div className="c-badge-row">
              <span className="c-badge">{ext || (type ? type.split('/')[1] : 'FILE')}</span>
              <span>{humanSize}</span>
            </div>
            
            <div className="c-media-frame">
              {isImage && (
                <img className="c-media-img" src={file.fileSource} alt={file.name} />
              )}
              {isVideo && (
                <video 
                  className="c-media-video" 
                  controls 
                  disablePictureInPicture 
                  playsInline 
                  preload="metadata" 
                  title={file.name}
                >
                  <source src={file.fileSource} type={type} />
                </video>
              )}
              {!isImage && !isVideo && (
                <div>No media content to display</div>
              )}
            </div>
            
            <div className="c-caption">
              <span className="c-name" title={file.name}>{file.name}</span>
              <a 
                className="c-btn-link" 
                href={file.fileSource} 
                target="_blank" 
                rel="noopener noreferrer"
                download={file.name}
              >
                Download
              </a>
            </div>
          </div>
        </div>
      );
    };
    // Attachment Chip Template Component
    const AttachmentChipTemplate = (props) => {
      const file = props.selectedFile;
      const isImage = !!(file && file.rawFile && typeof file.rawFile.type === 'string' && file.rawFile.type.indexOf('image/') === 0);
      const isVideo = !!(file && file.rawFile && typeof file.rawFile.type === 'string' && file.rawFile.type.indexOf('video/') === 0);

      return (
        <div className="c-attach">
          <div className="c-attach-thumb">
            {isImage && (
              <img className="c-attach-img" src={file.fileSource} alt={file.name} />
            )}
            {isVideo && (
              <span className="e-icons e-video"></span>
            )}
            {!isImage && !isVideo && (
              <span className="e-icons e-chat-file-icon"></span>
            )}
          </div>
          <div className="c-attach-body">
            <div className="c-attach-name" title={file.name}>{file.name}</div>
            <div className="c-attach-meta">{file.type || ''}</div>
          </div>
        </div>
      );
    };
    const attachmentSettings =  {
        attachmentTemplate: AttachmentChipTemplate,
        previewTemplate: PreviewTemplate,
        saveUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Save',
        removeUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Remove'
    };
    const currentUserModel = {
        id: "user1",
        user: "Albert"
    };
    return (
        // specifies the tag for render the Chat UI component
        <ChatUIComponent user={currentUserModel} className="chat-attachment-template" enableAttachments={true} attachmentSettings= {attachmentSettings} ></ChatUIComponent>
    );
}

ReactDOM.render(<App />, document.getElementById('container'));
import { ChatUIComponent, FileAttachmentSettingsModel, UserModel } from '@syncfusion/ej2-react-interactive-chat';
import * as React from 'react';
import * as ReactDOM from "react-dom";

function App() {

    // Preview Template Component
    const PreviewTemplate = (props: { selectedFile: any, index?: number }) => {
      const file = props.selectedFile;
      const type = (file?.rawFile?.type || file?.type || '').toLowerCase();
      const isImage = type.startsWith('image/');
      const isVideo = type.startsWith('video/');
      const sizeBytes = file?.size || 0;
      const humanSize = sizeBytes < 1024
        ? `${sizeBytes} B`
        : sizeBytes < 1024 * 1024
          ? `${(sizeBytes / 1024).toFixed(1)} KB`
          : `${(sizeBytes / (1024 * 1024)).toFixed(1)} MB`;
      const ext = (file?.name?.split('.').pop() || '').toUpperCase();

      return (
        <div className="c-preview--card">
          <div className="c-preview-card">
            <div className="c-badge-row">
              <span className="c-badge">{ext || (type ? type.split('/')[1] : 'FILE')}</span>
              <span>{humanSize}</span>
            </div>
            
            <div className="c-media-frame">
              {isImage && (
                <img className="c-media-img" src={file.fileSource} alt={file.name} />
              )}
              {isVideo && (
                <video 
                  className="c-media-video" 
                  controls 
                  disablePictureInPicture 
                  playsInline 
                  preload="metadata" 
                  title={file.name}
                >
                  <source src={file.fileSource} type={type} />
                </video>
              )}
              {!isImage && !isVideo && (
                <div>No media content to display</div>
              )}
            </div>
            
            <div className="c-caption">
              <span className="c-name" title={file.name}>{file.name}</span>
              <a 
                className="c-btn-link" 
                href={file.fileSource} 
                target="_blank" 
                rel="noopener noreferrer"
                download={file.name}
              >
                Download
              </a>
            </div>
          </div>
        </div>
      );
    };
    // Attachment Chip Template Component
    const AttachmentChipTemplate = (props: { selectedFile: any }) => {
      const file = props.selectedFile;
      const isImage = !!(file && file.rawFile && typeof file.rawFile.type === 'string' && file.rawFile.type.indexOf('image/') === 0);
      const isVideo = !!(file && file.rawFile && typeof file.rawFile.type === 'string' && file.rawFile.type.indexOf('video/') === 0);

      return (
        <div className="c-attach">
          <div className="c-attach-thumb">
            {isImage && (
              <img className="c-attach-img" src={file.fileSource} alt={file.name} />
            )}
            {isVideo && (
              <span className="e-icons e-video"></span>
            )}
            {!isImage && !isVideo && (
              <span className="e-icons e-chat-file-icon"></span>
            )}
          </div>
          <div className="c-attach-body">
            <div className="c-attach-name" title={file.name}>{file.name}</div>
            <div className="c-attach-meta">{file.type || ''}</div>
          </div>
        </div>
      );
    };
    const attachmentSettings: FileAttachmentSettingsModel =  {
        attachmentTemplate: AttachmentChipTemplate,
        previewTemplate: PreviewTemplate,
        saveUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Save',
        removeUrl: 'https://services.syncfusion.com/js/production/api/FileUploader/Remove'
    };
    const currentUserModel: UserModel = {
        id: "user1",
        user: "Albert"
    };
    return (
        // specifies the tag for render the Chat UI component
        <ChatUIComponent user={currentUserModel} className="chat-attachment-template" enableAttachments={true} attachmentSettings= {attachmentSettings} ></ChatUIComponent>
    );
}

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