简体   繁体   English

Busboy 文件事件未触发

[英]Busboy file event not firing

So, I have this post request which used to work fine but once I upgraded to Node 10 I can't seem to figure out why the file event completely stopped firing...所以,我有这个 post 请求,它过去工作正常,但是一旦我升级到 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);
});

I tried to do console.log(imageToBeUploaded);我试着做console.log(imageToBeUploaded); inside onFinish and it is always an empty object. Besides, any console logs inside onFile never seem to print.在 onFinish 内,它始终为空 object。此外,onFile 内的任何控制台日志似乎都不会打印。

I also tried without authenticate.FBAuth middleware but that didn't make any difference.我也尝试过不使用 authenticate.FBAuth 中间件,但这没有任何区别。

This is the error from bucket().upload() basically complaining that the path is invalid which makes sense since imageToBeUploaded is an empty object and hence imageToBeUploaded.filepath is undefined这是来自bucket().upload()的错误,基本上是抱怨路径无效,这是有道理的,因为imageToBeUploaded是空的 object,因此imageToBeUploaded.filepath undefined

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'
}

I am using Postman for the test and choosing form-data for body and File for the input type.我正在使用 Postman 进行测试,并为正文选择表单数据,为输入类型选择文件。 Made sure that Postman handled the Content-Type header setting it to multipart/form-data; boundary=<calculated when request is sent>确保 Postman 处理了 Content-Type header 并将其设置为multipart/form-data; boundary=<calculated when request is sent> multipart/form-data; boundary=<calculated when request is sent>

Also, this is the file containing authenticate.FBAuth just in case此外,这是包含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);
            });
    }
}

And here is package.json这是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
}

I fixed it我修好了它

The problem is that the code was migrated to docker from a cloud function. In the cloud function you use busboy.end(req.rawBody) since this is where the cloud function stores the request after consuming it.问题是代码从云 function 迁移到 docker。在云 function 中,您使用busboy.end(req.rawBody)因为这是云 function 在使用请求后存储请求的地方。 But after migration to docker the request is passed directly to the express route and req.rawBody is never populated.但是在迁移到 docker 之后,请求直接传递到快速路由并且req.rawBody永远不会被填充。 The solution is to just replace busboy.end(req.rawBody) with req.pipe(busboy)解决方案是将busboy.end(req.rawBody)替换为 req.pipe(busboy req.pipe(busboy)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM