Uploading files is one of the most common features in a web application nowadays. There are a lot of JavaScript libraries available that handle the file upload 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 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 using fetch()
:
const uploadFile = (file) => {
// add file to 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 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;
}
// ...
}
Handling File Upload on Server Side using Node.js
Here is a example code that handles the above file upload request in Node.js. I am using express-fileupload
— a simple Express middleware for uploading files. It parses multipart/form-data requests
, extracts the files if available, and make them available under 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 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);
}
});
Check out Uploading Files in Node.js and Express guide to learn in detailed how to handle file uploads in Node.js.
Handling File Upload on Server Side using Spring Boot
If you are planning to use Spring Boot for 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 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);
}
Check out 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.