FileUpload

FileUpload is an advanced uploader with dragdrop support, multi file uploads, auto uploading, progress tracking and validations.

Usage#

import { FileUpload } from 'primereact/fileupload';
<FileUpload></FileUpload>

Examples#

Basic#

FileUpload provides a customizable interface for file selection and uploading.

No file chosen
import { FileUploadInstance } from '@primereact/types/shared/fileupload';
import { ToastRegionInstance, ToastType } from '@primereact/types/shared/toast';
import { Button } from 'primereact/button';
import { FileUpload } from 'primereact/fileupload';
import { Message } from 'primereact/message';
import { Toast, toast } from 'primereact/toast';
 
const onUpload = () => {
    toast({
        title: 'Success',
        description: 'File Uploaded',
        group: 'basic-demo'
    });
};
 
export default function BasicDemo() {
    return (
        <div className="card">
            <FileUpload name="demo[]" url="/api/upload" accept="image/*" multiple maxFileSize={1000000} onUpload={onUpload}>
                {(instance: FileUploadInstance) => {
                    return (
                        <>
                            {instance.state.messages &&
                                instance.state.messages.length > 0 &&
                                instance.state.messages.map((msg, i) => (
                                    <Message key={i} severity="error" className="mb-2">
                                        <Message.Content>
                                            <Message.Text>{msg}</Message.Text>
                                        </Message.Content>
                                    </Message>
                                ))}
 
                            <div className="flex justify-between">
                                <div className="flex flex-wrap items-center gap-3">
                                    <Button onClick={instance.choose}>
                                        <i className="pi pi-plus" />
                                        Choose
                                    </Button>
                                    <span>{instance.hasFiles ? instance.state.files.map((file) => file.name).join(', ') : 'No file chosen'}</span>
                                </div>
                                <Button severity="secondary" onClick={instance.upload}>
                                    Upload
                                </Button>
                            </div>
                        </>
                    );
                }}
            </FileUpload>
 
            <Toast position="top-right" group="basic-demo">
                <Toast.Portal>
                    <Toast.Region>
                        {({ toast }: ToastRegionInstance) =>
                            toast?.toasts.map((toast: ToastType) => (
                                <Toast.Item key={toast.id} data={toast}>
                                    <div className="flex items-start gap-2">
                                        <div className="flex-1">
                                            <Toast.Title className="mb-1 -mt-0.5" />
                                            <Toast.Description />
                                        </div>
                                    </div>
                                    <Toast.Close as={Button} iconOnly severity={'secondary'} variant="text" size="small" className={'absolute top-2 right-2'}>
                                        <i className="pi pi-times"></i>
                                    </Toast.Close>
                                </Toast.Item>
                            ))
                        }
                    </Toast.Region>
                </Toast.Portal>
            </Toast>
        </div>
    );
}

Auto#

When auto property is enabled, a file gets uploaded instantly after selection.

import { FileUploadInstance } from '@primereact/types/shared/fileupload';
import { ToastRegionInstance, ToastType } from '@primereact/types/shared/toast';
import { Button } from 'primereact/button';
import { FileUpload } from 'primereact/fileupload';
import { Message } from 'primereact/message';
import { Toast, toast } from 'primereact/toast';
 
export default function AutoDemo() {
    const onUpload = () => {
        toast({
            title: 'Success',
            description: 'File Uploaded',
            group: 'auto-demo'
        });
    };
 
    return (
        <div className="card flex justify-center">
            <FileUpload name="demo[]" url="/api/upload" auto accept="image/*" maxFileSize={1000000} onUpload={onUpload}>
                {(instance: FileUploadInstance) => {
                    return (
                        <>
                            {instance.state.messages &&
                                instance.state.messages.length > 0 &&
                                instance.state.messages.map((msg, i) => (
                                    <Message key={i} severity="error" className="mb-2">
                                        <Message.Content>
                                            <Message.Text>{msg}</Message.Text>
                                        </Message.Content>
                                    </Message>
                                ))}
 
                            <div className="flex flex-wrap items-center gap-3">
                                <Button onClick={instance.choose}>
                                    <i className="pi pi-plus" />
                                    Browse
                                </Button>
                            </div>
                        </>
                    );
                }}
            </FileUpload>
 
            <Toast position="top-right" group="auto-demo">
                <Toast.Portal>
                    <Toast.Region>
                        {({ toast }: ToastRegionInstance) =>
                            toast?.toasts.map((toast: ToastType) => (
                                <Toast.Item key={toast.id} data={toast}>
                                    <div className="flex items-start gap-2">
                                        <div className="flex-1">
                                            <Toast.Title className="mb-1 -mt-0.5" />
                                            <Toast.Description />
                                        </div>
                                    </div>
                                    <Toast.Close as={Button} iconOnly severity={'secondary'} variant="text" size="small" className={'absolute top-2 right-2'}>
                                        <i className="pi pi-times"></i>
                                    </Toast.Close>
                                </Toast.Item>
                            ))
                        }
                    </Toast.Region>
                </Toast.Portal>
            </Toast>
        </div>
    );
}

Advanced#

Advanced uploader provides dragdrop support, multi file uploads, auto uploading, progress tracking and validations.

Drag and drop files to here to upload.
import { FileUploadInstance } from '@primereact/types/shared/fileupload';
import { ToastRegionInstance, ToastType } from '@primereact/types/shared/toast';
import { Button } from 'primereact/button';
import { FileUpload } from 'primereact/fileupload';
import { Message } from 'primereact/message';
import { ProgressBar } from 'primereact/progressbar';
import { Toast, toast } from 'primereact/toast';
 
export default function AdvancedDemo() {
    const onUpload = () => {
        toast({
            title: 'Success',
            description: 'File Uploaded',
            group: 'advanced-demo'
        });
    };
 
    return (
        <div className="card">
            <FileUpload name="demo[]" url="/api/upload" multiple accept="image/*" maxFileSize={1000000} className="border border-surface-200 dark:border-surface-700 rounded-md" onUpload={onUpload}>
                {(instance: FileUploadInstance) => {
                    return (
                        <>
                            <div className="flex items-center p-5 gap-2">
                                <Button onClick={instance.choose}>
                                    <i className="pi pi-plus" />
                                    Choose
                                </Button>
                                <Button severity="secondary" disabled={!instance.hasFiles} onClick={instance.upload}>
                                    <i className="pi pi-upload" />
                                    Upload
                                </Button>
                                <Button severity="secondary" disabled={!instance.hasFiles} onClick={instance.clear}>
                                    <i className="pi pi-times" />
                                    Cancel
                                </Button>
                            </div>
 
                            <FileUpload.Content>
                                {((instance.state.messages && instance.state.messages.length > 0) || instance.hasFiles) && (
                                    <div className="flex flex-col gap-4">
                                        {instance.state.messages &&
                                            instance.state.messages.length > 0 &&
                                            instance.state.messages.map((msg, i) => (
                                                <Message key={i} severity="error" className="mb-2">
                                                    <Message.Content>
                                                        <Message.Text>{msg}</Message.Text>
                                                    </Message.Content>
                                                </Message>
                                            ))}
 
                                        {instance.hasFiles && (
                                            <ProgressBar value={instance.state.progress}>
                                                <ProgressBar.Track style={{ height: '0.25rem' }}>
                                                    <ProgressBar.Indicator>
                                                        <ProgressBar.Label />
                                                    </ProgressBar.Indicator>
                                                </ProgressBar.Track>
                                            </ProgressBar>
                                        )}
                                    </div>
                                )}
 
                                <FileUpload.List />
 
                                {!instance.hasFiles && !instance.hasUploadedFiles && <div>Drag and drop files to here to upload.</div>}
                            </FileUpload.Content>
                        </>
                    );
                }}
            </FileUpload>
 
            <Toast position="top-right" group="advanced-demo">
                <Toast.Portal>
                    <Toast.Region>
                        {({ toast }: ToastRegionInstance) =>
                            toast?.toasts.map((toast: ToastType) => (
                                <Toast.Item key={toast.id} data={toast}>
                                    <div className="flex items-start gap-2">
                                        <div className="flex-1">
                                            <Toast.Title className="mb-1 -mt-0.5" />
                                            <Toast.Description />
                                        </div>
                                    </div>
                                    <Toast.Close as={Button} iconOnly severity={'secondary'} variant="text" size="small" className={'absolute top-2 right-2'}>
                                        <i className="pi pi-times"></i>
                                    </Toast.Close>
                                </Toast.Item>
                            ))
                        }
                    </Toast.Region>
                </Toast.Portal>
            </Toast>
        </div>
    );
}

Template#

Uploader UI can be customized with templating.

Drag and drop files to here to upload.

import { FileUploadInstance, FileUploadSelectEvent } from '@primereact/types/shared/fileupload';
import { Badge } from 'primereact/badge';
import { Button } from 'primereact/button';
import { FileUpload } from 'primereact/fileupload';
import { Message } from 'primereact/message';
import { ProgressBar } from 'primereact/progressbar';
import * as React from 'react';
 
export default function TemplateDemo() {
    const fileUploadRef = React.useRef<FileUploadInstance>(null);
    const [totalSize, setTotalSize] = React.useState(0);
    const [totalSizePercent, setTotalSizePercent] = React.useState(0);
 
    const onRemoveFileCallback = (cb: ((index: number) => void) | undefined, file: File, index: number) => {
        if (!fileUploadRef.current || !cb) return;
 
        const fileSizeStr = fileUploadRef.current.formatSize(file.size);
        const _totalSize = totalSize - parseInt(fileSizeStr);
 
        cb(index);
        setTotalSize(_totalSize);
        setTotalSizePercent(_totalSize / 10000);
    };
 
    const onSelect = (e: FileUploadSelectEvent) => {
        if (!fileUploadRef.current) return;
 
        let _totalSize = totalSize;
        const files = e.files;
 
        files.forEach((file) => {
            const fileSizeStr = fileUploadRef.current!.formatSize(file.size);
 
            _totalSize += parseInt(fileSizeStr);
        });
 
        setTotalSize(_totalSize);
        setTotalSizePercent(_totalSize / 10);
    };
 
    return (
        <div className="card">
            <FileUpload ref={fileUploadRef} name="demo[]" url="/api/upload" multiple accept="image/*" maxFileSize={1000000} className="border border-surface-200 dark:border-surface-700 rounded-md" onSelect={onSelect}>
                {(instance: FileUploadInstance) => {
                    return (
                        <>
                            <div className="flex items-center p-5 gap-2">
                                <div className="flex flex-wrap justify-between items-center flex-1 gap-4">
                                    <div className="flex gap-2">
                                        <Button onClick={instance.choose} iconOnly rounded variant="outlined" severity="secondary">
                                            <i className="pi pi-images" />
                                        </Button>
                                        <Button onClick={instance.upload} iconOnly rounded variant="outlined" severity="success" disabled={!instance.hasFiles}>
                                            <i className="pi pi-cloud-upload" />
                                        </Button>
                                        <Button onClick={instance.clear} iconOnly rounded variant="outlined" severity="danger" disabled={!instance.hasFiles}>
                                            <i className="pi pi-times" />
                                        </Button>
                                    </div>
                                    <ProgressBar value={totalSizePercent}>
                                        <ProgressBar.Track className="md:w-20rem w-full md:ml-auto">
                                            <ProgressBar.Indicator>
                                                <ProgressBar.Label />
                                            </ProgressBar.Indicator>
                                        </ProgressBar.Track>
                                    </ProgressBar>
                                </div>
                            </div>
                            <FileUpload.Content>
                                <div className="flex flex-col gap-8 pt-4">
                                    {instance.state.messages &&
                                        instance.state.messages.length > 0 &&
                                        instance.state.messages.map((msg, i) => (
                                            <Message key={i} severity="error" className="mb-2">
                                                <Message.Content>
                                                    <Message.Text>{msg}</Message.Text>
                                                </Message.Content>
                                            </Message>
                                        ))}
 
                                    {instance.hasFiles && (
                                        <>
                                            <h5 className="font-semibold">Pending</h5>
                                            <div className="flex flex-wrap gap-4">
                                                {instance.state.files.map((file, index) => (
                                                    <div key={file.name + file.type + file.size} className="p-8 rounded-border flex flex-col border border-surface items-center gap-4">
                                                        <div>
                                                            <img role="presentation" alt={file.name} src={URL.createObjectURL(file)} width="100" height="50" />
                                                        </div>
                                                        <span className="font-semibold text-ellipsis max-w-60 whitespace-nowrap overflow-hidden">{file.name}</span>
                                                        <div>{instance?.formatSize(file.size)}</div>
                                                        <Badge severity="warn">Pending</Badge>
                                                        <Button variant="text" rounded iconOnly severity="danger" onClick={() => onRemoveFileCallback(instance?.remove, file, index)}>
                                                            <i className="pi pi-times" />
                                                        </Button>
                                                    </div>
                                                ))}
                                            </div>
                                        </>
                                    )}
 
                                    {instance.hasUploadedFiles && (
                                        <>
                                            <h5 className="font-semibold">Completed</h5>
                                            <div className="flex flex-wrap gap-4">
                                                {instance.state.uploadedFiles.map((file, index) => (
                                                    <div key={file.name + file.type + file.size} className="p-8 rounded-border flex flex-col border border-surface items-center gap-4">
                                                        <div>
                                                            <img role="presentation" alt={file.name} src={URL.createObjectURL(file)} width="100" height="50" />
                                                        </div>
                                                        <span className="font-semibold text-ellipsis max-w-60 whitespace-nowrap overflow-hidden">{file.name}</span>
                                                        <div>{instance.formatSize(file.size)}</div>
                                                        <Badge severity="success" className="mt-4">
                                                            Completed
                                                        </Badge>
                                                        <Button variant="text" rounded iconOnly severity="danger" onClick={() => instance?.removeUploadedFile(index)}>
                                                            <i className="pi pi-times" />
                                                        </Button>
                                                    </div>
                                                ))}
                                            </div>
                                        </>
                                    )}
 
                                    {!instance.hasFiles && !instance.hasUploadedFiles && (
                                        <>
                                            <div className="flex items-center justify-center flex-col">
                                                <i className="pi pi-cloud-upload border-2 rounded-full p-8 text-4xl text-muted-color" />
                                                <p className="mt-6 mb-0">Drag and drop files to here to upload.</p>
                                            </div>
                                        </>
                                    )}
                                </div>
                            </FileUpload.Content>
                        </>
                    );
                }}
            </FileUpload>
        </div>
    );
}

Custom Upload#

Uploading implementation can be overridden by enabling customUpload property. This sample, displays the image on the client side with a grayscale filter.

import { FileUploadHandlerEvent, FileUploadInstance } from '@primereact/types/shared/fileupload';
import { Button } from 'primereact/button';
import { FileUpload } from 'primereact/fileupload';
import * as React from 'react';
 
export default function CustomUploadDemo() {
    const [src, setSrc] = React.useState<string | null>(null);
 
    const onFileSelect = (event: FileUploadHandlerEvent) => {
        const file = event.files[0];
        const reader = new FileReader();
 
        reader.onload = async (e) => {
            if (e.target?.result && typeof e.target.result === 'string') {
                setSrc(e.target.result);
            }
        };
 
        reader.readAsDataURL(file);
    };
 
    return (
        <div className="card flex flex-col items-center gap-6">
            <FileUpload url="/api/upload" auto customUpload uploadHandler={onFileSelect}>
                {(instance: FileUploadInstance) => {
                    return (
                        <div className="flex flex-wrap items-center gap-3">
                            <Button onClick={instance.choose} severity="secondary" variant="outlined">
                                <i className="pi pi-plus" />
                                Browse
                            </Button>
                        </div>
                    );
                }}
            </FileUpload>
            {src && <img src={src} alt="Image" className="shadow-md rounded-xl w-full sm:w-64" style={{ filter: 'grayscale(100%)' }} />}
        </div>
    );
}