I’m trying to upload a file through Express File Upload
but getting an undefined value of the function in which it is being called.
I have this function which checks if the user chose a single file or multiple files. To keep it simple I am just going to show the issue in single file upload. That is req.files.fileInput
is an object instead of an array of objects.
Here’s the code:
const fileCheck = ( file ) => { if ( Array.isArray( file ) ) { // ignore this part of the if block as I'm testing it out with single file upload console.log( 'THE USER WANTS TO UPLOAD MULTIPLE FILES' ); } else if ( typeof file === 'object' ) { console.log( 'THE USER WANTS TO UPLOAD A SINGLE FILE' ); const uploadPath = `./resources/images/${file.name}`; file.mv( uploadPath, function ( err ) { if ( err ) { console.error( err ); return { success: false, message: 'Something went wrong. Please upload again!', data: null }; } return { success: true, message: 'File Uploaded Successfully!', data: file.name }; }); } }; const { success, message, data } = fileCheck(req.files.fileInput); // IT IS UNDEFINED BUT IT IS SUPPOSED TO BE TRUE IF FILE UPLOAD IS SUCCESSFUL. // IT IS ALSO UNDEFINED INSTEAD OF FALSE IF THERE IS AN ERROR IN FILE UPLOAD. console.log( success );
I get this error:
TypeError: Cannot destructure property 'success' of '(intermediate value)' as it is undefined.
Seems like fileCheck
function’s return statement isn’t getting triggered after using it in .mv() method. What could be the reason here? And what can I do to solve it?
Advertisement
Answer
You’re only returning from the file.mv()
callback function, you need to return file.mv()
as well, such that it percolates up to your fileCheck
function.
Do this
return file.mv(uploadPath, function (err) { if (err) { console.error(err); return { success: false, message: 'Something went wrong. Please upload again!', data: null, }; } return { success: true, message: 'File Uploaded Successfully!', data: file.name, }; });
EDIT
Unfortunately the file.mv()
doesn’t seem to return the result of its callback function by default.
Consider returning a promise from fileCheck
like this
const fileCheck = ( file ) => { if ( Array.isArray( file ) ) { console.log( 'THE USER WANTS TO UPLOAD MULTIPLE FILES' ); } else if ( typeof file === 'object' ) { console.log( 'THE USER WANTS TO UPLOAD A SINGLE FILE' ); const uploadPath = `./resources/images/${file.name}`; return new Promise((resolve, reject) => file.mv( uploadPath, function ( err ) { if ( err ) { console.error( err ); return reject({ success: false, message: 'Something went wrong. Please upload again!', data: null }); } return resolve({ success: true, message: 'File Uploaded Successfully!', data: file.name }); }); } };
And using fileCheck
like this
const { success, message, data } = await fileCheck(req.files.fileInput); console.log( success );
NB: You have to make the parent function where fileCheck
is being called async
in other to use await