When uploading files in web development, there are generally two common methods: using FormData and directly through the request body. Each method has its own characteristics and use cases.
Uploading via FormData
Method: FormData is a way to encode data as a set of key-value pairs. When you use FormData to upload files, it is typically used in combination with multipart/form-data encoding type. This is the standard way to upload files in HTML forms.
// HTML form with input type 'file'
// <input type="file" id="fileInput">
const fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', function(event) {
const file = event.target.files[0];
const formData = new FormData();
formData.append('file', file);
fetch('/upload', {
method: 'POST',
body: formData
// Note: no need to explicitly set the Content-Type header here
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
});
Use Case: It is ideal for uploading files along with other form fields, such as text input, checkboxes, etc.
Compatibility: Widely supported by most browsers and can be used with XMLHttpRequest (XHR) and the newer Fetch API.
Advantages:
- Can handle multiple types of data (files, text, binary data).
- Easy to append additional fields and compatible with traditional form-based web applications.
- Generally, no need to manually set headers as they are automatically set, which includes setting the Content-Type to multipart/form-data and the correct boundary.
Disadvantages:
- Slightly more overhead due to the multipart encoding.
Uploading via Request Body
Method: Directly sending the file data in the body of an HTTP request. Here, you can set the Content-Type header to the file's MIME type (like image/jpeg, application/pdf, etc.) and place the file's raw data in the request body.
// HTML form with input type 'file'
// <input type="file" id="fileInput">
const fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', function(event) {
const file = event.target.files[0];
fetch('/upload', {
method: 'POST',
body: file,
headers: {
'Content-Type': file.type
}
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
});
Use Case: Suited for APIs or services where you're uploading only a file, without any additional form fields.
Compatibility: Works with both XMLHttpRequest and Fetch API. Requires manual setting of headers and handling of file data.
Advantages:
- More efficient for sending only file data as it avoids the overhead of multipart encoding.
- Offers more control over the request, such as setting custom headers.
Disadvantages:
Requires manual handling of content types and boundaries if needed.
Not suitable for situations where you need to send additional data alongside the file.
Summary
FormData is best for situations where a file is being uploaded as part of a form with other fields. It's more browser-friendly and straightforward to use. Direct Body Upload is more efficient for APIs where you're only uploading a file and need more control over the request. It's less suited for traditional form-based uploads and requires more manual setup.
Top comments (7)
And for very large files you can decide to streamline file from HD, pipe it chunk by chunk to the server. Of course server must have special implementation that to process this kind of upload.
That's a good point. I'll write on uploading large files separately as well
Ive also seen one where people comvert the file to a 64 bit string then send the file as a string to the API
Do you mean base64 string as part of post request body?
yeah ..like
{
"image: "base64string....."
}
the file itself is then stored as a string in the database as well, I know it sounds a bit unconventional but in some situations you dont have any other option.
Yea, did that recently.
what are your thoughts on it?