File upload with drag and drop in vanilla JavaScript
By Flavio Copes
Learn how to build file upload with drag and drop in vanilla JavaScript using the ondragover, ondragleave, and ondrop events, then POST the files as FormData.
I wrote about the Drag and Drop API concepts in the past.
Now I want to show how I implemented a simple file upload with drag and drop on a site I’m building.
Identify an HTML element you want people to drag their files to:
<div
class="dropzone"
ondragover=`dragOverHandler(event)`
ondragleave=`dragLeaveHandler(event)`
ondrop=`dropHandler(event)`
>
...
</div>
ondragover is fired when people are dragging a file on the element. We can use this to add some style, for example a dashed border.
ondragleave is the opposite, when we exit the drop area.
I used this JS to add a dragging_over class to the element, and style it with CSS:
function dragOverHandler(event) {
event.preventDefault();
const dropzone = document.querySelector('#dropzone');
dropzone.classList.add('dragging_over');
}
function dragLeaveHandler(event) {
event.preventDefault();
const dropzone = document.querySelector('#dropzone');
dropzone.classList.remove('dragging_over');
}
#dropzone.dragging_over {
border: 2px dashed #fff;
background-color: #666;
}
ondrop is fired when the file (or multiple files!) is dropped on the area.
That’s where the action happens.
I gather the files, check they’re images (I only want images in this example), and POST the data to /api/upload:
async function dropHandler(event) {
event.preventDefault()
const endpoint = `/api/upload`
if (event.dataTransfer.items) {
const formData = new FormData()
formData.append('action', 'upload')
for (let item of event.dataTransfer.items) {
if (item.kind === 'file') {
const file = item.getAsFile()
if (file) {
//I only want images
if (!file.type.match('image.*')) {
alert('only images supported')
return
}
formData.append('files', file)
}
}
}
try {
const response = await fetch(endpoint, {
method: 'POST',
body: formData,
})
if (response.ok) {
console.log('File upload successful')
} else {
console.error('File upload failed', response)
}
} catch (error) {
console.error('Error uploading file', error)
}
}
}
How to handle that server-side depends on your server.
With Astro I got the data using:
const formData = await Astro.request.formData()
console.log(formData.getAll('files')) Related posts about platform: