I'm trying to implement custom ajax form submission using jQuery. In short, it does something like this:
It works fine with simple inputs and selects, but the problems begin when I'm trying to submit files. I have decided to implement a function that reads file content as Blob and transforms it to String in Base64 and creates an object for a file that will be processed on server-side, so the structure of my form paload might look something like this:
{
name: 'John',
surname: 'Doe',
roles: ['CLIENT', 'ADMIN'],
photo: {
fileName: 'photo.jpg',
mimeType: 'image/jpeg'
content: '%base64_encoded_String%'
}
}
I was looking into FileReader to work with file content and have written something like this:
function fileToBase64( file ) {
let reader = new FileReader()
let fileContent
reader.onload = function() {
fileContent = reader.result
}
reader.readAsDataURL( file )
return {
fileName: file.name,
mimeType: file.type,
content: fileContent
}
}
However, having not so much experience with javascript I cannot really wrap my head around the promises: it turns out whatever is happening while reading a File happens after I return the object, thus content is undefined. How can I ensure the file is read before the return is happening? I saw a FileReaderSync solution but it seems that now it is removed from browsers.
Basically, my code for getting field values is called inside a $( 'form' ).on( 'submit' ) function and looks like this:
let fieldIds = someFunctionThatGetsIdsForForm()
fieldIds.map( id => {
let field = $( '#' + id )
let isFileInput = field.is( 'input' ) && field.attr( 'type' ) === 'file'
let name = field.attr( 'name' )
// process value according to input type
if ( isFileInput ) {
let files = field[0].files
let fileDatas = []
// process all files from this input
for (let i = 0; i < files.length; i++) {
let file = files.item(i)
fileDatas.push( fileToBase64( file ) ) // how do I wait for this to complete before going further?
}
output[name] = fileDatas.length === 1 ? fileDatas[0] : fileDatas // either a single file or multiple
} else {
output[name] = field.val()
}
} )
Any insight into awaiting of async processes like reading is appreciated.