FileUpload

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

No file chosen
basic-demo

Usage#

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

Examples#

Auto#

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

auto-demo
'use client';
import { Plus } from '@primeicons/react/plus';
import { Times } from '@primeicons/react/times';
import { toast } from '@primereact/headless/toaster';
import { FileUploadRootInstance } from '@primereact/types/shared/fileupload';
import { ToasterRegionInstance, ToastType } from '@primereact/types/shared/toaster';
import { Button } from '@primereact/ui/button';
import { FileUpload } from '@primereact/ui/fileupload';
import { Message } from '@primereact/ui/message';
import { Toast } from '@primereact/ui/toast';
import { Toaster } from '@primereact/ui/toaster';

export default function AutoDemo() {
    const onUpload = () => {
        toast({
            title: 'Success',
            description: 'File Uploaded',
            group: 'auto-demo'
        });
    };

    return (
        <div className="flex justify-center">
            <FileUpload.Root name="demo[]" url="/api/upload" auto accept="image/*" maxFileSize={1000000} onUpload={onUpload}>
                {(instance: FileUploadRootInstance) => {
                    return (
                        <>
                            {instance.state.messages &&
                                instance.state.messages.length > 0 &&
                                instance.state.messages.map((msg, i) => (
                                    <Message.Root key={i} severity="error" className="mb-2">
                                        <Message.Content>
                                            <Message.Text>{msg}</Message.Text>
                                        </Message.Content>
                                    </Message.Root>
                                ))}

                            <div className="flex flex-wrap items-center gap-3">
                                <Button onClick={instance.choose}>
                                    <Plus />
                                    Browse
                                </Button>
                            </div>
                        </>
                    );
                }}
            </FileUpload.Root>

            <Toaster.Root position="top-right" group="auto-demo">
                <Toaster.Portal>
                    <Toaster.Region>
                        {({ toaster }: ToasterRegionInstance) =>
                            toaster?.toasts.map((toast: ToastType) => (
                                <Toast.Root key={toast.id} toast={toast}>
                                    <div className="grid grid-cols-[auto_1fr] items-start gap-3">
                                        <Toast.Icon className="[&>svg]:size-3.5 mt-1 " />
                                        <div>
                                            <Toast.Title />
                                            <Toast.Description className="mt-1" />
                                            <Toast.Action as={Button} size="small" className="mt-3" />
                                        </div>
                                    </div>
                                    <Toast.Close
                                        as={Button}
                                        iconOnly
                                        severity={'secondary'}
                                        variant="text"
                                        size="small"
                                        className={'absolute top-2 right-2'}
                                    >
                                        <Times />
                                    </Toast.Close>
                                </Toast.Root>
                            ))
                        }
                    </Toaster.Region>
                </Toaster.Portal>
            </Toaster.Root>
        </div>
    );
}

Advanced#

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

Drag and drop files to here to upload.
advanced-demo
'use client';
import { Plus } from '@primeicons/react/plus';
import { Times } from '@primeicons/react/times';
import { Upload } from '@primeicons/react/upload';
import { toast } from '@primereact/headless/toaster';
import { FileUploadRootInstance } from '@primereact/types/shared/fileupload';
import { ToasterRegionInstance, ToastType } from '@primereact/types/shared/toaster';
import { Button } from '@primereact/ui/button';
import { FileUpload } from '@primereact/ui/fileupload';
import { Message } from '@primereact/ui/message';
import { ProgressBar } from '@primereact/ui/progressbar';
import { Toast } from '@primereact/ui/toast';
import { Toaster } from '@primereact/ui/toaster';

export default function AdvancedDemo() {
    const onUpload = () => {
        toast({
            title: 'Success',
            description: 'File Uploaded',
            group: 'advanced-demo'
        });
    };

    return (
        <div>
            <FileUpload.Root
                name="demo[]"
                url="/api/upload"
                multiple
                accept="image/*"
                maxFileSize={1000000}
                className="border border-surface-200 dark:border-surface-700 rounded-md"
                onUpload={onUpload}
            >
                {(instance: FileUploadRootInstance) => {
                    return (
                        <>
                            <div className="flex items-center p-5 gap-2">
                                <Button onClick={instance.choose}>
                                    <Plus />
                                    Choose
                                </Button>
                                <Button severity="secondary" disabled={!instance.hasFiles} onClick={instance.upload}>
                                    <Upload />
                                    Upload
                                </Button>
                                <Button severity="secondary" disabled={!instance.hasFiles} onClick={instance.clear}>
                                    <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.Root key={i} severity="error" className="mb-2">
                                                    <Message.Content>
                                                        <Message.Text>{msg}</Message.Text>
                                                    </Message.Content>
                                                </Message.Root>
                                            ))}

                                        {instance.hasFiles && (
                                            <ProgressBar.Root value={instance.state.progress}>
                                                <ProgressBar.Track style={{ height: '0.25rem' }}>
                                                    <ProgressBar.Indicator>
                                                        <ProgressBar.Label />
                                                    </ProgressBar.Indicator>
                                                </ProgressBar.Track>
                                            </ProgressBar.Root>
                                        )}
                                    </div>
                                )}

                                <FileUpload.List />

                                {!instance.hasFiles && !instance.hasUploadedFiles && <div>Drag and drop files to here to upload.</div>}
                            </FileUpload.Content>
                        </>
                    );
                }}
            </FileUpload.Root>

            <Toaster.Root position="top-right" group="advanced-demo">
                <Toaster.Portal>
                    <Toaster.Region>
                        {({ toaster }: ToasterRegionInstance) =>
                            toaster?.toasts.map((toast: ToastType) => (
                                <Toast.Root key={toast.id} toast={toast}>
                                    <div className="grid grid-cols-[auto_1fr] items-start gap-3">
                                        <Toast.Icon className="[&>svg]:size-3.5 mt-1 " />
                                        <div>
                                            <Toast.Title />
                                            <Toast.Description className="mt-1" />
                                            <Toast.Action as={Button} size="small" className="mt-3" />
                                        </div>
                                    </div>
                                    <Toast.Close
                                        as={Button}
                                        iconOnly
                                        severity={'secondary'}
                                        variant="text"
                                        size="small"
                                        className={'absolute top-2 right-2'}
                                    >
                                        <Times />
                                    </Toast.Close>
                                </Toast.Root>
                            ))
                        }
                    </Toaster.Region>
                </Toaster.Portal>
            </Toaster.Root>
        </div>
    );
}

Template#

Uploader UI can be customized with templating.

Drag and drop files to here to upload.

template-demo
'use client';
import { FileUploadRootInstance, FileUploadSelectEvent } from '@primereact/types/shared/fileupload';
import { Badge } from '@primereact/ui/badge';
import { Button } from '@primereact/ui/button';
import { FileUpload } from '@primereact/ui/fileupload';
import { Message } from '@primereact/ui/message';
import { ProgressBar } from '@primereact/ui/progressbar';
import * as React from 'react';
import { Times } from '@primeicons/react/times';
import { CloudUpload } from '@primeicons/react/cloud-upload';
import { Images } from '@primeicons/react/images';

export default function TemplateDemo() {
    const fileUploadRef = React.useRef<FileUploadRootInstance>(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>
            <FileUpload.Root
                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: FileUploadRootInstance) => {
                    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">
                                            <Images />
                                        </Button>
                                        <Button
                                            onClick={instance.upload}
                                            iconOnly
                                            rounded
                                            variant="outlined"
                                            severity="success"
                                            disabled={!instance.hasFiles}
                                        >
                                            <CloudUpload />
                                        </Button>
                                        <Button
                                            onClick={instance.clear}
                                            iconOnly
                                            rounded
                                            variant="outlined"
                                            severity="danger"
                                            disabled={!instance.hasFiles}
                                        >
                                            <Times />
                                        </Button>
                                    </div>
                                    <ProgressBar.Root value={totalSizePercent}>
                                        <ProgressBar.Track className="md:w-20rem w-full md:ml-auto">
                                            <ProgressBar.Indicator>
                                                <ProgressBar.Label />
                                            </ProgressBar.Indicator>
                                        </ProgressBar.Track>
                                    </ProgressBar.Root>
                                </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.Root key={i} severity="error" className="mb-2">
                                                <Message.Content>
                                                    <Message.Text>{msg}</Message.Text>
                                                </Message.Content>
                                            </Message.Root>
                                        ))}

                                    {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)}
                                                        >
                                                            <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)}
                                                        >
                                                            <Times />
                                                        </Button>
                                                    </div>
                                                ))}
                                            </div>
                                        </>
                                    )}

                                    {!instance.hasFiles && !instance.hasUploadedFiles && (
                                        <>
                                            <div className="flex items-center justify-center flex-col">
                                                <CloudUpload className="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.Root>
        </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.

custom-upload-demo
'use client';
import { FileUploadHandlerEvent, FileUploadRootInstance } from '@primereact/types/shared/fileupload';
import { Button } from '@primereact/ui/button';
import { FileUpload } from '@primereact/ui/fileupload';
import * as React from 'react';
import { Plus } from '@primeicons/react/plus';

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="flex flex-col items-center gap-6">
            <FileUpload.Root url="/api/upload" auto customUpload uploadHandler={onFileSelect}>
                {(instance: FileUploadRootInstance) => {
                    return (
                        <div className="flex flex-wrap items-center gap-3">
                            <Button onClick={instance.choose} severity="secondary" variant="outlined">
                                <Plus />
                                Browse
                            </Button>
                        </div>
                    );
                }}
            </FileUpload.Root>
            {src && <img src={src} alt="Image" className="shadow-md rounded-xl w-full sm:w-64" style={{ filter: 'grayscale(100%)' }} />}
        </div>
    );
}