I have an Express.js app which I use a REST API to interact with Firebase Storage and Realtime Database. I set up a Firebase project where I use Firebase Functions. I have one main function which is basically the entry point for all requests to my Express app:
// export express app to functions
exports.api = functions.https.onRequest(app);
where app
is my Express app initialized.
One of the routes is used to upload an image to Firebase Storage. Here is the code for it:
/* POST upload user profile picture. */
router.post('/:username/upload_profile_picture', async function(req, res, next) {
try {
const bb = Busboy({ headers: req.headers });
let fileData = null;
let fileBlob = null;
bb.on('file', function (fieldname, file, filename, encoding, mimetype) {
const filepath = path.join(os.tmpdir(), filename.filename);
fileData = { filePath: filepath, type: mimetype };
file.pipe(fs.createWriteStream(filepath));
});
bb.on('finish', async () => {
const profilePicture = await UserRepository.uploadProfilePicture(fileData.filePath, req.params.username);
if (profilePicture == null) {
res.status(400).json({ message: "Image upload failed" });
} else {
res.status(200).json({ message: "Image uploaded successfully", profilePicture: profilePicture });
}
fs.unlinkSync(fileData.filePath);
});
req.pipe(bb);
} catch (error) {
next(error);
}
});
And here is the corresponding function called in my UserRepository:
exports.uploadProfilePicture= async (filePath, user) => {
const file = fs.readFileSync(filePath);
const imageRef = storage_ref(storage, 'profilePictures/' + user);
try {
await uploadBytes(imageRef, file.buffer);
console.log('Uploaded file to firebase');
const url = await getDownloadURL(imageRef);
return url;
} catch (error) {
console.log(error);
}
}
When I run my Express app locally using npm run dev
, images are uploading successfully. However whenever I use the Firebase Emulator, I get the following error:
> Error: Unexpected end of form
> at Multipart._final (/Users/cesar/ProgrammingProjects/Democrastyle/backend/node_modules/busboy/lib/types/multipart.js:588:17)
> at callFinal (node:internal/streams/writable:698:12)
> at prefinish (node:internal/streams/writable:710:7)
> at finishMaybe (node:internal/streams/writable:720:5)
> at Writable.end (node:internal/streams/writable:634:5)
> at onend (node:internal/streams/readable:705:10)
> at process.processTicksAndRejections (node:internal/process/task_queues:77:11)
> Emitted 'error' event on Multipart instance at:
> at Multipart.onerror (node:internal/streams/readable:785:14)
> at Multipart.emit (node:events:513:28)
> at emitErrorNT (node:internal/streams/destroy:151:8)
> at emitErrorCloseNT (node:internal/streams/destroy:116:3)
> at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
I read somewhere that the Multer library was causing this issue because Firebase does not support it, and that's why I migrated to using Busboy but I am still getting the same error. Using the Firebase Emulator, all other routes work fine. Only the routes that contain form-data are failing (although everything works locally).
N.B: I tried deploying the Firebase Functions but I get the same behaviour as the Emulator.