使用NodeJS和Busboy在Firebase上上传多个图像

时间:2019-10-19 06:23:15

标签: node.js firebase image-uploading busboy

我创建了使用NodeJS和Busboy在Firebase上载单个图像的函数,该函数返回图像URL。允许的图像扩展名仅为.jpg.png。它将生成随机文件名并使用storageBucket创建文件路径。

但是,我正在努力重构此功能,因此我可以上传多张图像。我尝试了几次,但没有运气。如果所有图像均已成功上传,则它应返回图像URL的数组。

这是我上传单张图片的功能:

const { admin, db } = require("./admin");
const config = require("./config");

exports.uploadImage = (req, res, url, folder) => {
    const BusBoy = require("busboy");
    const path = require("path");
    const os = require("os");
    const fs = require("fs");

    const busboy = new BusBoy({ headers: req.headers });

    let imageFileName;
    let imageToBeUploaded = {};

    busboy.on("file", (fieldname, file, filename, encoding, mimetype) => {
        if (mimetype !== "image/jpeg" && mimetype !== "image/png") {
            return res
                .status(400)
                .json({ error: "Wrong file type submitted!" });
        }
        // Getting extension of any image
        const imageExtension = filename.split(".")[
            filename.split(".").length - 1
        ];
        // Setting filename
        imageFileName = `${Math.round(
            Math.random() * 1000000000
        )}.${imageExtension}`;
        // Creating path
        const filepath = path.join(os.tmpdir(), imageFileName);
        imageToBeUploaded = { filepath, mimetype };
        file.pipe(fs.createWriteStream(filepath));
    });
    busboy.on("finish", () => {
        admin
            .storage()
            .bucket()
            .upload(imageToBeUploaded.filepath, {
                destination: `${folder}/${imageFileName}`,
                resumable: false,
                metadata: {
                    metadata: {
                        contentType: imageToBeUploaded.mimetype
                    }
                }
            })
            .then(() => {
                const imageUrl = `https://firebasestorage.googleapis.com/v0/b/${config.storageBucket}/o${folder}%2F${imageFileName}?alt=media`;
                if (url === `/users/${req.user.alias}`) {
                    return db.doc(`${url}`).update({ imageUrl });
                } else {
                    return res.json({ imageUrl });
                }
            })
            .then(() => {
                return res.json({
                    message: "Image uploaded successfully!"
                });
            })
            .catch(err => {
                console.log(err);
                return res.status(500).json({ error: err.code });
            });
    });
    busboy.end(req.rawBody);
};

有什么建议继续吗?

2 个答案:

答案 0 :(得分:1)

您的代码差不多完成了,您要做的就是创建一个Promise数组并等待所有解析。

let imageFileName = {}
let imagesToUpload = []
let imageToAdd = {}
//This triggers for each file type that comes in the form data
busboy.on("file", (fieldname, file, filename, encoding, mimetype) => {
    if (mimetype !== "image/jpeg" && mimetype !== "image/png") {
        return res
            .status(400)
            .json({ error: "Wrong file type submitted!" });
    }
    // Getting extension of any image
    const imageExtension = filename.split(".")[
        filename.split(".").length - 1
    ];
    // Setting filename
    imageFileName = `${Math.round(
        Math.random() * 1000000000
    )}.${imageExtension}`;
    // Creating path
    const filepath = path.join(os.tmpdir(), imageFileName);
    imageToAdd = { 
       imageFileName
       filepath, 
       mimetype };
    file.pipe(fs.createWriteStream(filepath));
    //Add the image to the array
    imagesToUpload.push(imageToAdd);
   });

busboy.on("finish", () => {
        let promises = []
        let imageUrls = []
        imagesToUpload.forEach(imageToBeUploaded => { 
imageUrls.push(`https://firebasestorage.googleapis.com/v0/b/${config.storageBucket}/o${folder}%2F${imageFileName}?alt=media`)
                    promises.push(admin
                        .storage()
                        .bucket()
                        .upload(imageToBeUploaded.filepath, {
                             destination: `${folder}/${imageFileName}`,
                             resumable: false,
                             metadata: {
                                 metadata: {
                                     contentType: imageToBeUploaded.mimetype
                                 }
                             }
                         }))
                })
          try{      
              await Promises.all(resolve)
              res.status(200).json({msg: 'Successfully uploaded all images', imageUrls})
}catch(err){ res.status(500).json(err) }
            });
        busboy.end(req.rawBody);

有了这些,您应该可以全部上传它们,只需将所有的Promise放入数组中并使用Promise.all方法来等待它们解决即可。我使用async / await做到了,因为这就是我一直这样做的方式,但是我想您在使用回调进行操作时将没有问题。

代码也很混乱,但这主要是因为我不知道如何使用此文本编辑器,希望您仍然能够理解它?

答案 1 :(得分:1)

塞缪尔·维拉(Samuel Vera)的答案几乎是正确的。推送到 imageUrls 数组时会有一些输入错误和逻辑错误。

此处,已修复完整代码:

const BusBoy = require('busboy');
const path = require('path');
const os = require('os');
const fs = require('fs');

let fields = {};

const busboy = new BusBoy({ headers: request.headers });

let imageFileName = {};
let imagesToUpload = [];
let imageToAdd = {};
let imageUrls = [];

busboy.on('field', (fieldname, fieldvalue) => {
    fields[fieldname] = fieldvalue;
});

busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
    if (mimetype !== 'image/jpeg' && mimetype !== 'image/png') {
        return res
            .status(400)
            .json({ error: 'Wrong file type submitted!' });
    }

    // Getting extension of any image
    const imageExtension = filename.split('.')[
        filename.split('.').length - 1
    ];

    // Setting filename
    imageFileName = `${Math.round(Math.random() * 1000000000)}.${imageExtension}`;

    // Creating path
    const filepath = path.join(os.tmpdir(), imageFileName);
    imageToAdd = {
        imageFileName,
        filepath,
        mimetype,
    };

    file.pipe(fs.createWriteStream(filepath));
    //Add the image to the array
    imagesToUpload.push(imageToAdd);
});

busboy.on('finish', async () => {
    let promises = [];

    imagesToUpload.forEach((imageToBeUploaded) => {
        imageUrls.push(
            `https://firebasestorage.googleapis.com/v0/b/${config.storageBucket}/o/${imageToBeUploaded.imageFileName}?alt=media`
        );
        promises.push(
            admin
                .storage()
                .bucket()
                .upload(imageToBeUploaded.filepath, {
                    resumable: false,
                    metadata: {
                        metadata: {
                            contentType: imageToBeUploaded.mimetype,
                        },
                    },
                })
        );
    });

    try {
        await Promise.all(promises);
        
        return response.json({
            message: `Images URL: ${imageUrls}`,
        });
        
    } catch (err) {
        console.log(err);
        response.status(500).json(err);
    }
});

busboy.end(request.rawBody);

无论如何,谢谢塞缪尔:)