无法使用 Firebase 功能将图像上传到 Firebase 存储

问题描述 投票:0回答:4

这是我的代码:-

exports.uploadImage = (req, res) => {

    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) => {

        const imageExtension = filename.split('.')[filename.split('.').length - 1];
        imageFileName = `${Math.round(Math.random() * 100000000000)}.${imageExtension}`;
        const filepath = path.join(os.tmpdir(), imageFileName);
        imageToBeUploaded = { filepath, mimetype };
        file.pipe(fs.createWriteStream(filepath));

    });

    busboy.on('finish', () => {

        console.log('Busboy on started');    

        //code breaks here    
        admin.storage().bucket().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`;
            console.log('logging image url' + imageUrl);
            return db.doc(`/users/${req.user.handle}`).update({ imageUrl })
        })
        .then(() => {
            return res.json({ message: 'Image uploaded successfully' });
        })
        .catch(err => {
            console.error(err);
            return res.status(500).json({ error: err.code });
        })
    });
    busboy.end(req.rawBody);
}

我已经在评论中提到了我的代码在哪里中断,我收到的错误是

Error: Cannot parse response as JSON: Not Found
message: 'Cannot parse response as JSON: Not Found'

错误消息显示无法将响应解析为

JSON
。这是否意味着 firebase 的响应不是 JSON?我在请求的标头中有一个令牌,在正文中有一个图像作为表单数据。我真的不知道出了什么问题,请帮忙

firebase google-cloud-firestore google-cloud-functions google-cloud-storage firebase-storage
4个回答
1
投票

不幸的是,我无法识别 JSON 解析错误,因此我改写了代码,使其更加精简,就像 @robsiemb 所回避的那样。

您的

uploadImage
函数似乎被配置为一些中间件,所以我在下面做了同样的事情。此代码将使用从
Reference.push().key
生成的唯一文件名将上传的数据直接流式传输到 Cloud Storage,以防止冲突。

在下面的代码中,

  • 上传的文件将存储在类似于:
    userData/someUserId/images/-JhLeOlGIEjaIOFHR0xd.png
  • 的位置
  • 图像的原始 URL 不会存储在数据库中,因为除非文件对象或包含的存储桶公开,否则它将需要一个签名 URL,该 URL 最多只能持续 7 天(见下文)。
  • 可以接受并上传多个文件。如果不希望出现这种情况,请为 BusBoy
     实例配置
    限制。
  • 添加了针对非 POST 请求和丢失文件条目的基本错误处理。
// import Firebase libraries & initialize const admin = require('firebase-admin'); admin.initializeApp(); // initializes from environment variables // import required modules const BusBoy = require('busboy'); exports.uploadImage = (req, res) => { if (req.method !== 'POST') { res.sendStatus(405); // 405 METHOD_NOT_ALLOWED return; } let busboy = new BusBoy({headers: req.headers}); // add {limits: {files: 1}} to limit to only a single file upload let bucket = admin.storage().bucket(); let db = admin.firestore(); let storageFilepath; let storageFile; // Note: Currently only the last file is saved to `/users/${req.user.handle}` busboy.on('file', (fieldname, file, filename, encoding, mimetype) => { let fileext = filename.match(/\.[0-9a-z]+$/i)[0]; storageFilepath = `userData/${req.user.handle}/images/` + getUniqueName() + fileext; storageFile = bucket.file(storageFilepath); file.pipe(storageFile.createWriteStream({ gzip: true })); }) .on('finish', () => { if (!storageFile) { res.status(400).json({error: 'expected file'}); // 400 BAD_REQUEST return; } db.doc(`/users/${req.user.handle}`).update({ imagePath: storageFilepath }) .then(() => { res.status(201).json({ message: 'Image uploaded successfully' }); // 201 CREATED }) .catch((err) => { console.error(err); res.status(500).json({ error: err.code }); // 500 INTERNAL_SERVER_ERROR }); }) .on('error', (err) => { console.error(err); res.status(500).json({ error: err.code }); }); req.pipe(busboy); }); function getUniqueName() { // push() without arguments returns a ThennableReference, which we'll abuse for it's key generation return admin.database().ref().push().key; }

如果您确实希望上传的图像可供公开访问,您可以使用以下添加到

.on('finish', ...)
函数中的
File.makePublic()
处理程序:

.on('finish', () => { if (!storageFile) { res.status(400).json({error: 'expected file'}); // 400 BAD_REQUEST return; } storageFile.makePublic() .then(() => { return db.doc(`/users/${req.user.handle}`).update({ imagePath: storageFilepath, imageUrl: `https://storage.googleapis.com/${config.storageBucket}/${storageFilepath}` }); }) .then(() => { res.status(201).json({ message: 'Image uploaded successfully' }); // 201 CREATED }) .catch((err) => { console.error(err); res.status(500).json({ error: err.code }); // 500 INTERNAL_SERVER_ERROR }); })
    

0
投票
找到问题的解决方案!

本质上 - 您需要设置您的 Google 应用程序凭据。进入 firebase 并查看您的设置。您需要设置环境变量 GOOGLE_APPLICATION_CREDENTIALS,以便 Firebase 在您访问这些文件时拥有您的凭据。

https://firebase.google.com/docs/admin/setup?authuser=1了解更多信息。

完成此操作后,请检查 Firebase 中您正在处理的每个区域的安全设置。这应该可以解决问题(这绝对是安全问题,而不是您的代码)。

对于那些正在观看的人来说,这也是有问题的教程。

https://www.youtube.com/watch?v=m_u6P5k0vP0&t=7661s .


0
投票
就我而言,配置了错误的存储桶 ID - 更正后我能够上传文件


0
投票
检查 Firebase 控制台>>存储>>(选项卡)规则下的存储配置, 这是默认配置,将标志更改为 true:

rules_version = '2'; service firebase.storage { match /b/{bucket}/o { match /{allPaths=**} { allow read, write: if false; } } }
    
© www.soinside.com 2019 - 2024. All rights reserved.