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.
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>
);
}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 uploader provides dragdrop support, multi file uploads, auto uploading, progress tracking and validations.
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>
);
}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>
);
}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>
);
}