I've been following this FormData tutorial here, however have yet to understand how the formData object works.
<input type="file" id="file-id" class="w300px rounded4px" name="file" placeholder="PDF file">
<button class="btn-upload-pdf" ng-click="asub.uploadPDF()">Upload</button>
this.uploadPDF = () => {
const formData = new FormData();
const fileInput = document.getElementById('file-id');
const file = fileInput.files[0];
formData.append('pdf-file', file);
console.log('formData', formData)
return ApiFactory.insightPDF(formData).then((res) => {
console.log('res', res);
return res;
});
};
When I log out the fileInput
object .files[0]
I see the file I just attached:
It would seem to mean that this object should be enough to send along to the POST. However this is the next step:
formData.append('pdf-file', file);
I log out formData
before I send it into my Factory and this is the result, I don't see the key pdf-file
or that PDF anywhere, just a bunch of methods? Where does the file get appended too? How does formData contain the actual PDF?
I need to attach something from the formData object I presume:
const insightPDF = (formData) => {
console.log(' formData', formData)
return $http.post('/app/api/insights_pdf', formData).then((res) => {
console.log('PDF uploaded res', res)
return res;
}).catch(apiError);
};
Content-Type: undefined
When posting objects created by the FormData API it is important to set the content type header to undefined
.
const insightPDF = (formData) => {
console.log(' formData', formData)
var config = { headers: {'Content-Type': undefined} };
return $http.post('/app/api/insights_pdf', formData, config)
.then((res) => {
console.log('PDF uploaded res', res)
return res;
}).catch(apiError);
};
Normally the AngularJS framework, automatically add the content type header as application/json
which overrides the content type set by the XHR Send() method. When the XHR API sends a FormData object, it automatically sets the content type to multipart/form-data
with the proper boundary.
From the Docs:
The $http service will automatically add certain HTTP headers to all requests
To explicitly remove a header automatically added via
$httpProvider.defaults.headers
on a per request basis, Use the headers property, setting the desired header toundefined
. For example:var req = { method: 'POST', url: 'http://example.com', headers: { 'Content-Type': undefined }, data: { test: 'test' } }
— AngularJS $http Service API Reference - Setting HTTP Headers
FormData objects like blobs are host-defined objects non-native to JavaScript. Not all of their properties can be seen by console.log
or console.dir
. Files are a special type of blob. The data is not necessarily loaded from disk. Usually, the data is streamed from disk only when needed by a specific API.
Content in multipart/form-data
uses base64 encoding which adds 33% extra overhead. If uploading only one file, it is more efficient to send the file blob directly.
//MORE Efficient; Avoids base64 encoding overhead
const insightPDF = (dataObject) => {
var config = { headers: {'Content-Type': undefined} };
return $http.post('/app/api/insights_pdf', dataObject, config)
.then((res) => {
console.log('PDF uploaded res', res)
return res;
}).catch(apiError);
};
var file = inputElem[0].files[0];
insightPDF(file);
If the server can accept binary content directly, it is best to send files that way. The XHR API will automatically set the content type to that of the file.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With