首页 > 解决方案 > 通过云功能上传文件 Admin SDK - Broken Files

问题描述

我一直在尝试通过firebase云功能(onRequest方法)将文件(主要是图像)上传到firebase存储。我不得不从它的base64表单上传文件。使用下面的代码,我能够实现它,但上传后文件似乎被破坏了。

const functions = require('firebase-functions');
const admin = require('firebase-admin');

const bucket = admin.storage().bucket();
const database = admin.database();
const express = require('express');
const cors = require('cors');

const safetyLogsAPI = express();
safetyLogsAPI.use(cors({ origin: true }));

safetyLogsAPI.post('/', async (req, res) => {
    try {
        const { 
            attachments,
            projectId
        } = req.body;
        const safetyKey = database.ref('safetyLogs')
          .child(projectId)
          .push().key;
        if(attachments && Array.isArray(attachments)) {
          if (attachments.length > 0) {
            for (let index = 0; index < attachments.length; index++) {
              const base64Obj = attachments[index];
              const { content, fileName, contentType } = base64Obj;
              const stream = require('stream');
              const bufferStream = new stream.PassThrough();
              bufferStream.end(Buffer.from(content, 'base64'));
              const fullPath = `SafetyIncidentLog/Images/${projectId}/${safetyKey}/${fileName}`;
              const file = bucket.file(fullPath);
              const metadata = {
                projectId,
                safetyLogId: safetyKey,
                createdTimestamp: Date.now(),
                systemGenerated: 'false',
                fileType: 'Image',
                fileName,
                path: fullPath
              };
              bufferStream.pipe(file.createWriteStream({
                metadata: {
                  contentType,
                  metadata
                },
                public: true,
                validation: "md5"
              }))
                .on('error', (err) => {
                  console.log('Error Occured');
                  console.log(err);
                })
                .on('finish', () => {
                  console.log('File Upload Successfull');
                });
            }
          }
        }
        return res.status(200).send({
            code: 200,
            message: 'Success'
        });
        
    } catch (error) {
        console.log(error);
        return res.status(500).send({
            code:500,
            message: 'Internal Server Error',
            error: error.message
        });
    }
});

module.exports = functions.https.onRequest(safetyLogsAPI);

我已经尝试过这种方法,前缀部分data:image/png;base64存在和消除。在这两种方式中,我都看到了损坏的图像。那么我哪里出错了。有没有更好的方法来制作它?

提前致谢。

另外,我尝试这样做的方法是推荐的方法吗?对于个人资料图片上传和对话图片附件等用例,是否推荐这种方式,还是推荐从客户端直接上传?

标签: javascriptnode.jsfirebasegoogle-cloud-functionsfirebase-storage

解决方案


使用 Cloud Functions HTTP 触发器,只要您向客户端发送响应,请求就会终止并且函数会关闭。任何未完成的异步工作可能永远不会完成。

我在您的代码中看到的是您在上传完成之前发送了响应。我可以看到您的呼叫res.status(200).send()在您开始上传后立即发生。相反,您的代码应该等到响应完成后再发送响应,可能使用on('finish')and on('error')


推荐阅读