使用Express(Multer)向Firebase传图失败,报TypeError错误
问题:Firebase后端图片上传报错TypeError: Cannot read properties of undefined (reading 'mimetype')
TypeError: Cannot read properties of undefined (reading 'mimetype')
基于Firebase搭建自定义后端实现图片上传功能时遇到上述错误,移除mimetype属性后仍出现其他属性相关错误,相关代码如下:
index.ts
import * as multer from "multer"; // dotenv.config(); const app = express(); initializeApp(firebaseConfig); // admin.initializeApp(functions.config().functions); admin.firestore(); export const openai = new OpenAIApi(configuration); export const upload = multer({storage: multer.memoryStorage()}); app.use(bodyParser.json()); app.use(express.urlencoded({extended: false})); app.use(cors({origin: true})); routesConfig(app); export const api = functions.https.onRequest(app);
route
export function routesConfig(app: Application) { app.get("/", (req, res) => res.status(200).send("Welcome home!!!")); // registrations api--------------------------------------------------- app.post("/verifyuser", upload.single("name"), verifyUserAccount); }
verifyUserAccount函数
export async function verifyUserAccount(req: Request, res: Response): Promise<Response<unknown>> { try { const dd = await Uploading.uploadData( req.body.files, "gbenga", "gbenga"); // const data = dataAuthService; return res.status(200).send({message: "Succesfull", dd}); } catch (error) { logger.error("error is coming from wher" + error); return res.status(400).send(error); } }
Uploading.uploadData类
import { getStorage, ref, uploadBytesResumable } from "firebase/storage"; import { logger } from "firebase-functions/v1"; import { injectable } from "inversify"; @injectable() export class Uploading { static async uploadData(file:any, userId:string, postId:string): Promise<string> { const bucket = getStorage(); // const bucketDomain = "gs://uneleap-9b858.appspot.com"; try { const dateTime = Date.now(); const fileName = `${postId}/${userId}/${dateTime}`; const storageRef = ref(bucket, fileName); const metadata = { contentType: file.mimetype, }; await uploadBytesResumable(storageRef, file.buffer, metadata); return fileName; // // const subPaths = file.fieldname.split("/"); // // const fileName = subPaths[subPaths.length - 1]; // const destination = `${postId}/${userId}/${postId}`; // await bucket.bucket().upload(file.path, { destination, resumable: true }); // const uploadedUrl = `https://${bucketDomain}/${destination}`; // Construct the URL\ // const uploadedImageLinks = await Promise.all(uploadedUrl); // return uploadedImageLinks; } catch (error) { logger.error("Error =>", error); throw new Error("this is from error"); } } }
解决方案
错误核心原因
使用multer.single()解析文件后,文件对象不会存放在req.body中,而是挂载到req.file上。当前传递的req.body.files是undefined,导致后续访问file.mimetype触发报错。
具体修改步骤
修正文件获取方式
修改verifyUserAccount函数,将req.body.files替换为req.file,同时增加文件存在性校验:export async function verifyUserAccount(req: Request, res: Response): Promise<Response<unknown>> { try { // 校验是否有文件上传 if (!req.file) { return res.status(400).send({ message: "请上传文件" }); } const dd = await Uploading.uploadData(req.file, "gbenga", "gbenga"); return res.status(200).send({ message: "成功", dd }); } catch (error) { logger.error("错误来源:" + error); return res.status(400).send(error); } }确认字段名一致性
路由中upload.single("name")的参数"name"是前端上传文件的表单字段名,必须和前端保持一致。比如前端文件输入框的name属性要设为name:<input type="file" name="name" />如果前端用其他字段名(如
avatar),需同步修改路由参数为upload.single("avatar")。前端请求格式校验
前端发送请求时必须设置Content-Type为multipart/form-data,否则multer无法解析文件。
内容的提问来源于stack exchange,提问作者Gbenga B Ayannuga
相关产品推荐
相关产品推荐

