FileUpload is an advanced uploader with dragdrop support, multi file uploads, auto uploading, progress tracking and validations.
import { FileUpload } from 'primereact/fileupload';<FileUpload></FileUpload>FileUpload provides a customizable interface for file selection and uploading.
'use client';
import { toast } from '@primereact/headless/toast';
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 } from 'primereact/toast';
const onUpload = () => {
toast({
title: 'Success',
description: 'File Uploaded',
group: 'basic-demo'
});
};
export default function BasicDemo() {
return (
<div>
<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>
);
}
When auto property is enabled, a file gets uploaded instantly after selection.
'use client';
import { toast } from '@primereact/headless/toast';
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 } from 'primereact/toast';
export default function AutoDemo() {
const onUpload = () => {
toast({
title: 'Success',
description: 'File Uploaded',
group: 'auto-demo'
});
};
return (
<div className="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 uploader provides dragdrop support, multi file uploads, auto uploading, progress tracking and validations.
'use client';
import { toast } from '@primereact/headless/toast';
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 } from 'primereact/toast';
export default function AdvancedDemo() {
const onUpload = () => {
toast({
title: 'Success',
description: 'File Uploaded',
group: 'advanced-demo'
});
};
return (
<div>
<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>
);
}
Uploader UI can be customized with templating.
Drag and drop files to here to upload.
'use client';
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>
<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>
);
}
Uploading implementation can be overridden by enabling customUpload property. This sample, displays the image on the client side with a grayscale filter.
'use client';
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="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>
);
}