Uploading files is one of the most common features in a web application nowadays. There are many JavaScript libraries available that handle file uploads like a breeze.
But let's not load a whole library just for this single feature that can be easily handled in native JavaScript using Fetch API. Fetch is a promise-based modern replacement of XHR for making HTTP requests in the browser.
Fetch API file upload
Let's add the following HTML input element to your website:
<input type="file" id="avatar">
Now add an event listener on the input that will be triggered when the user chooses a file:
// select file input
const input = document.getElementById('avatar')
// add event listener
input.addEventListener('change', () => {
uploadFile(input.files[0])
})
Next, add uploadFile()
method that receives a File
object as input and uploads it on the server with fetch()
using the FormData
interface:
const uploadFile = file => {
// add the file to the FormData object
const fd = new FormData()
fd.append('avatar', file)
// send `POST` request
fetch('/upload-avatar', {
method: 'POST',
body: fd
})
.then(res => res.json())
.then(json => console.log(json))
.catch(err => console.error(err))
}
Do not set the
Content-Type
header for multi-part request withfetch()
. The browser will automatically add the content type header, including the form boundary.
Validate file type & size
You can also validate the properties (like file type and file size) of the file before starting uploading on the server:
const uploadFile = file => {
// check file type
if (!['image/jpeg', 'image/gif', 'image/png', 'image/svg+xml'].includes(file.type)) {
console.log('Only images are allowed.')
return
}
// check file size (< 2MB)
if (file.size > 2 * 1024 * 1024) {
console.log('File must be less than 2MB.')
return
}
// ...
}
Uploading file on the server using Node.js
Here is an example that handles the above file upload request in Node.js. I am using the express-fileupload
library, a simple Express middleware for uploading files. It parses multipart/form-data
requests, extracts the files if available, and makes them available under the req.files
property:
app.post('/upload-avatar', async (req, res) => {
try {
if (!req.files) {
res.send({
status: false,
message: 'No file uploaded'
})
} else {
// Use the name of the input field (i.e. "avatar") to retrieve the uploaded file
let avatar = req.files.avatar
// Use the mv() method to place the file in the upload directory (i.e. "uploads")
avatar.mv('./uploads/' + avatar.name)
//send response
res.send({
status: true,
message: 'File is uploaded',
data: {
name: avatar.name,
mimetype: avatar.mimetype,
size: avatar.size
}
})
}
} catch (err) {
res.status(500).send(err)
}
})
Read the Uploading Files in Node.js and Express guide to learn how to handle file uploads in Node.js.
Uploading file on the server using Spring Boot
If you are planning to use Spring Boot for the back end, here is an example code snippet that processes the above file upload request in Spring Boot:
@PostMapping("/upload-avatar")
@ResponseBody
public ResponseEntity<String> fileUpload(MultipartFile avatar) {
try {
// upload directory - change it to your own
String UPLOAD_DIR = "/opt/uploads";
// create a path from the file name
Path path = Paths.get(UPLOAD_DIR, avatar.getOriginalFilename());
// save the file to `UPLOAD_DIR`
// make sure you have permission to write
Files.write(path, avatar.getBytes());
}
catch (Exception ex) {
ex.printStackTrace();
return new ResponseEntity<>("Invalid file format!!", HttpStatus.BAD_REQUEST);
}
return new ResponseEntity<>("File uploaded!!", HttpStatus.OK);
}
Read the Uploading Files in Spring Boot guide for handling single and multiple file uploads in a Spring Boot application.
✌️ Like this article? Follow me on Twitter and LinkedIn. You can also subscribe to RSS Feed.