Busboy文件事件未触发

问题描述

所以,我有一个可以正常工作的帖子请求,但是一旦我升级到Node 10,我似乎无法弄清文件事件为什么完全停止触发...

router.post('/uploadImage',authenticate.FBAuth,(req,res) => {
    const busboy = new BusBoy({ headers: req.headers });
    let imageFileName;
    let imagetoBeUploaded = {};

    busboy.on('file',function onFile(fieldname,file,filename,encoding,mimetype) {
        console.log('onFile started');
        
        if (mimetype !== 'image/png' && mimetype !== 'image/jpeg') {
            return res.status(400).json({ error: 'Unsupported file format' });
        }

        const imageExtension = path.extname(filename);
        imageFileName = `${Math.round(Math.random() * 100000000000)}.${imageExtension}`;
        console.log(imageFileName);

        const filepath = path.join(os.tmpdir(),imageFileName);
        console.log(filepath);

        imagetoBeUploaded = { filepath,mimetype };
        console.log(imagetoBeUploaded);

        file.pipe(fs.createWriteStream(filepath));
    });

    busboy.on('finish',function onFinish() {
        admin
            .storage()
            .bucket(config.storageBucket)
            .upload(imagetoBeUploaded.filepath,{
                resumable: false,Metadata: {
                    Metadata: {
                        contentType: imagetoBeUploaded.mimetype
                    }
                }
            })
            .then(() => {
                const imageUrl = `https://firebasestorage.googleapis.com/v0/b/${config.storageBucket}/o/${imageFileName}?alt=media`;
                return db.doc(`/users/${req.user.handle}`).update({ imageUrl });
            })
            .then(() => {
                return res.json({ message: 'Image uploaded successfully' });
            })
            .catch(error => {
                console.error(error);
                return res.status(500).json({ error: error.code });
            });
    });

    busboy.end(req.rawBody);
});

我尝试在onFinish内执行console.log(imagetoBeUploaded);,它始终是一个空对象。此外,onFile内的任何控制台日志似乎都无法打印。

我也尝试了不使用authenticate.FBAuth中间件,但这没什么区别。

这是来自bucket().upload()错误,基本上是抱怨路径无效,这是有道理的,因为imagetoBeUploaded一个空对象,因此imagetoBeUploaded.filepathundefined

TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined
    at validateString (internal/validators.js:121:11)
    at Object.basename (path.js:1156:5)
    at Bucket.upload (/Users/mac/Dev/meows/server/node_modules/firebase-admin/node_modules/@google-cloud/storage/build/src/bucket.js:2493:38)
    at /Users/mac/Dev/meows/server/node_modules/firebase-admin/node_modules/@google-cloud/promisify/build/src/index.js:69:28
    at new Promise (<anonymous>)
    at Bucket.wrapper (/Users/mac/Dev/meows/server/node_modules/firebase-admin/node_modules/@google-cloud/promisify/build/src/index.js:54:16)
    at Busboy.onFinish (/Users/mac/Dev/meows/server/routes/profileRouter.js:116:14)
    at Busboy.emit (events.js:315:20)
    at Busboy.emit (/Users/mac/Dev/meows/server/node_modules/busboy/lib/main.js:37:33)
    at /Users/mac/Dev/meows/server/node_modules/busboy/lib/types/multipart.js:304:17 {
  code: 'ERR_INVALID_ARG_TYPE'
}

我正在使用邮递员进行测试,并为正文选择表单数据,为输入类型选择文件。确保邮递员处理了Content-Type标头,将其设置为multipart/form-data; boundary=<calculated when request is sent>

此外,这是一个包含authenticate.FBAuth文件,以防万一

const admin = require('firebase-admin');
const db = admin.firestore();

module.exports = {
    FBAuth: (req,res,next) => {
        let idToken;
        if (req.headers.authorization == null || !req.headers.authorization.startsWith('bearer ')) {
            console.log('Unrecognized token format');
            return res.status(400).json({ error: 'Unauthorized operation' });
        }
        else {
            idToken = req.headers.authorization.split('bearer ')[1];
        }
        return admin.auth().verifyIdToken(idToken)
            .then(decodedToken => {
                req.user = decodedToken;
                return db.collection('users')
                    .where('userId','==',req.user.uid)
                    .limit(1)
                    .get()
                    .then(data => {
                        req.user.handle = data.docs[0].data().handle;
                        req.user.imageUrl = data.docs[0].data().imageUrl;
                        return next();
                    });
            })
            .catch(error => {
                console.log('Error verifying token ',error);
                return res.status(403).json(error);
            });
    }
}

这是package.json

{
  "name": "functions","description": "Cloud Functions for Firebase","scripts": {
    "start": "node index.js"
  },"engines": {
    "node": "10"
  },"dependencies": {
    "body-parser": "^1.19.0","busboy": "^0.3.1","express": "^4.17.1","firebase": "^7.15.0","firebase-admin": "^8.6.0","unirest": "^0.6.0"
  },"private": true
}

解决方法

我修复了

问题是代码已从云功能迁移到docker。在云功能中,您可以使用busboy.end(req.rawBody),因为这是使用后云功能存储请求的地方。但是在迁移到docker之后,请求会直接传递到快速路由,并且永远不会填充req.rawBody。解决方案是将busboy.end(req.rawBody)替换为req.pipe(busboy)