React Dropzone
Simple HTML5 drag-drop zone with React.js
Upload Multiple Files
Drop files here or click to upload.
(This is just a demo drop zone. Selected files are not actually uploaded.)
// ** React Imports
import { Fragment, useState } from 'react'
// ** MUI Imports
import Box from '@mui/material/Box'
import List from '@mui/material/List'
import Button from '@mui/material/Button'
import ListItem from '@mui/material/ListItem'
import Typography from '@mui/material/Typography'
import IconButton from '@mui/material/IconButton'
// ** Icon Imports
import Icon from 'src/@core/components/icon'
// ** Third Party Imports
import { useDropzone } from 'react-dropzone'
const FileUploaderMultiple = () => {
// ** State
const [files, setFiles] = useState([])
// ** Hooks
const { getRootProps, getInputProps } = useDropzone({
onDrop: acceptedFiles => {
setFiles(acceptedFiles.map(file => Object.assign(file)))
}
})
const renderFilePreview = file => {
if (file.type.startsWith('image')) {
return <img width={38} height={38} alt={file.name} src={URL.createObjectURL(file)} />
} else {
return <Icon icon='tabler:file-description' />
}
}
const handleRemoveFile = file => {
const uploadedFiles = files
const filtered = uploadedFiles.filter(i => i.name !== file.name)
setFiles([...filtered])
}
const fileList = files.map(file => (
<ListItem key={file.name}>
<div className='file-details'>
<div className='file-preview'>{renderFilePreview(file)}</div>
<div>
<Typography className='file-name'>{file.name}</Typography>
<Typography className='file-size' variant='body2'>
{Math.round(file.size / 100) / 10 > 1000
? {(Math.round(file.size / 100) / 10000).toFixed(1)} mb
: {(Math.round(file.size / 100) / 10).toFixed(1)} kb}
</Typography>
</div>
</div>
<IconButton onClick={() => handleRemoveFile(file)}>
<Icon icon='tabler:x' fontSize={20} />
</IconButton>
</ListItem>
))
const handleRemoveAllFiles = () => {
setFiles([])
}
return (
<Fragment>
<div {...getRootProps({ className: 'dropzone' })}>
<input {...getInputProps()} />
<Box sx={{ display: 'flex', textAlign: 'center', alignItems: 'center', flexDirection: 'column' }}>
<Box
sx={{
mb: 8.75,
width: 48,
height: 48,
display: 'flex',
borderRadius: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: theme => rgba({theme.palette.customColors.main}, 0.08)
}}
>
<Icon icon='tabler:upload' fontSize='1.75rem' />
</Box>
<Typography variant='h4' sx={{ mb: 2.5 }}>
Drop files here or click to upload.
</Typography>
<Typography sx={{ color: 'text.secondary' }}>
(This is just a demo drop zone. Selected files are not actually uploaded.)
</Typography>
</Box>
</div>
{files.length ? (
<Fragment>
<List>{fileList}</List>
<div className='buttons'>
<Button color='error' variant='outlined' onClick={handleRemoveAllFiles}>
Remove All
</Button>
<Button variant='contained'>Upload Files</Button>
</div>
</Fragment>
) : null}
</Fragment>
)
}
export default FileUploaderMultiple
Upload Single Files
Drop files here or click to upload.
(This is just a demo drop zone. Selected files are not actually uploaded.)
// ** React Imports
import { useState } from 'react'
// ** MUI Imports
import Box from '@mui/material/Box'
import Typography from '@mui/material/Typography'
// ** Icon Imports
import Icon from 'src/@core/components/icon'
// ** Third Party Imports
import { useDropzone } from 'react-dropzone'
const FileUploaderSingle = () => {
// ** State
const [files, setFiles] = useState([])
// ** Hooks
const { getRootProps, getInputProps } = useDropzone({
multiple: false,
accept: {
'image/*': ['.png', '.jpg', '.jpeg', '.gif']
},
onDrop: acceptedFiles => {
setFiles(acceptedFiles.map(file => Object.assign(file)))
}
})
const img = files.map(file => (
<img key={file.name} alt={file.name} className='single-file-image' src={URL.createObjectURL(file)} />
))
return (
<Box {...getRootProps({ className: 'dropzone' })} sx={files.length ? { height: 450 } : {}}>
<input {...getInputProps()} />
{files.length ? (
img
) : (
<Box sx={{ display: 'flex', textAlign: 'center', alignItems: 'center', flexDirection: 'column' }}>
<Box
sx={{
mb: 8.75,
width: 48,
height: 48,
display: 'flex',
borderRadius: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: theme => rgba({theme.palette.customColors.main}, 0.08)
}}
>
<Icon icon='tabler:upload' fontSize='1.75rem' />
</Box>
<Typography variant='h4' sx={{ mb: 2.5 }}>
Drop files here or click to upload.
</Typography>
<Typography sx={{ color: 'text.secondary' }}>
(This is just a demo drop zone. Selected files are not actually uploaded.)
</Typography>
</Box>
)}
</Box>
)
}
export default FileUploaderSingle
Upload Files with Restrictions
Drop files here or click to upload.
Allowed *.jpeg, *.jpg, *.png, *.gif
Max 2 files and max size of 2 MB
// ** React Imports
import { Fragment, useState } from 'react'
// ** MUI Imports
import Box from '@mui/material/Box'
import List from '@mui/material/List'
import Button from '@mui/material/Button'
import ListItem from '@mui/material/ListItem'
import Typography from '@mui/material/Typography'
import IconButton from '@mui/material/IconButton'
// ** Icon Imports
import Icon from 'src/@core/components/icon'
// ** Third Party Components
import toast from 'react-hot-toast'
import { useDropzone } from 'react-dropzone'
const FileUploaderRestrictions = () => {
// ** State
const [files, setFiles] = useState([])
// ** Hooks
const { getRootProps, getInputProps } = useDropzone({
maxFiles: 2,
maxSize: 2000000,
accept: {
'image/*': ['.png', '.jpg', '.jpeg', '.gif']
},
onDrop: acceptedFiles => {
setFiles(acceptedFiles.map(file => Object.assign(file)))
},
onDropRejected: () => {
toast.error('You can only upload 2 files & maximum size of 2 MB.', {
duration: 2000
})
}
})
const renderFilePreview = file => {
if (file.type.startsWith('image')) {
return <img width={38} height={38} alt={file.name} src={URL.createObjectURL(file)} />
} else {
return <Icon icon='tabler:file-description' />
}
}
const handleRemoveFile = file => {
const uploadedFiles = files
const filtered = uploadedFiles.filter(i => i.name !== file.name)
setFiles([...filtered])
}
const fileList = files.map(file => (
<ListItem key={file.name}>
<div className='file-details'>
<div className='file-preview'>{renderFilePreview(file)}</div>
<div>
<Typography className='file-name'>{file.name}</Typography>
<Typography className='file-size' variant='body2'>
{Math.round(file.size / 100) / 10 > 1000
? {(Math.round(file.size / 100) / 10000).toFixed(1)} mb
: {(Math.round(file.size / 100) / 10).toFixed(1)} kb}
</Typography>
</div>
</div>
<IconButton onClick={() => handleRemoveFile(file)}>
<Icon icon='tabler:x' fontSize={20} />
</IconButton>
</ListItem>
))
const handleRemoveAllFiles = () => {
setFiles([])
}
return (
<Fragment>
<div {...getRootProps({ className: 'dropzone' })}>
<input {...getInputProps()} />
<Box sx={{ display: 'flex', textAlign: 'center', alignItems: 'center', flexDirection: 'column' }}>
<Box
sx={{
mb: 8.75,
width: 48,
height: 48,
display: 'flex',
borderRadius: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: theme => rgba({theme.palette.customColors.main}, 0.08)
}}
>
<Icon icon='tabler:upload' fontSize='1.75rem' />
</Box>
<Typography variant='h4' sx={{ mb: 2.5 }}>
Drop files here or click to upload.
</Typography>
<Typography sx={{ color: 'text.secondary' }}>Allowed *.jpeg, *.jpg, *.png, *.gif</Typography>
<Typography sx={{ color: 'text.secondary' }}>Max 2 files and max size of 2 MB</Typography>
</Box>
</div>
{files.length ? (
<Fragment>
<List>{fileList}</List>
<div className='buttons'>
<Button color='error' variant='outlined' onClick={handleRemoveAllFiles}>
Remove All
</Button>
<Button variant='contained'>Upload Files</Button>
</div>
</Fragment>
) : null}
</Fragment>
)
}
export default FileUploaderRestrictions
