I'm making a simple code to upload an image to Firebase using Firebase-Admin (NOT firebase), NodeJS, Express & Multer but for the life of me it's not working at all.
This is my code:
const functions = require("firebase-functions");
const app = require("express")();
const { bucket } = require("./util/admin");
const multer = require("multer");
const storage = multer.memoryStorage();
const upload = multer({
storage: storage,
limits: { fileSize: 8 * 1024 * 1024 },
fileFilter: (req, file, cb) => {
if (!file.originalname.match(/\.(jpg|jpeg|png)$/)) {
return cb(new Error("Only image files are allowed!"), false);
}
cb(null, true);
},
});
app.post("/uploadImage", upload.single("file"), async (req, res) => {
console.log(req.file);
if (!req.file) {
return res.status(400).send("No file uploaded.");
}
const fileName = `uploads/${Date.now()}_${req.file.originalname}`;
try {
const fileUpload = bucket.file(fileName);
const blobStream = fileUpload.createWriteStream({
metadata: {
contentType: req.file.mimetype,
},
});
blobStream.on("error", (error) => {
console.error("Blob stream error:", error);
return res.status(500).json({ error: error.message });
});
blobStream.on("finish", async () => {
await fileUpload.makePublic();
const publicUrl = `https://storage.googleapis.com/${bucket.name}/${fileName}`;
res.status(200).json({
message: "File uploaded successfully",
url: publicUrl,
});
});
blobStream.end(req.file.buffer);
} catch (error) {
console.error("Upload error:", error);
res.status(500).json({ error: "Internal server error" });
}
});
exports.api = functions.https.onRequest(app);
but I keep getting the same error when I run FIREBASE SERVE and use Postman to test it out:
Error: Unexpected end of form
> at Multipart._final (/Users/user/Desktop/FitStop-Functions/functions/node_modules/busboy/lib/types/multipart.js:588:17)
> at prefinish (node:internal/streams/writable:906:14)
> at finishMaybe (node:internal/streams/writable:920:5)
> at Writable.end (node:internal/streams/writable:835:5)
> at onend (node:internal/streams/readable:946:10)
> at process.processTicksAndRejections (node:internal/process/task_queues:77:11)
I've surefed the entire web to make sure I'm using the correct syntax and code, I even used GPT to double check it, and looks like all the code is correct. But why isn't it working???
I've been banging my head against the wall for 4 days now but with no sign of success!
PLEASE HELP!
ps. I had GPT go through the debug file, and it suggested that the issue might be because Multer depends on Busboy, which makes me believe that Busboy might be the culprit here. but I'm still not sure.
Firebase Functions use the body-parser middleware to automatically parse incoming requests. For multipart/form-data requests, this can cause issues because the stream that Multer tries to parse has already been consumed. This is why you're seeing the "Unexpected end of form" error, it's a result of the request's body stream being in an unexpected state by the time Multer tries to access it.
You can check Google documentation for more details here
You've two options:
1- void Direct File Uploads to Firebase Functions: Instead of uploading files directly to a Firebase Function, consider uploading them to Firebase Storage. This approach bypasses the need to parse multipart/form-data within your function.
2- Use a Middleware for Parsing: you can make a custom middleware approach that directly handles the raw request body, using busboy.