Функция загрузки работает локально, но не работает после развертывания в Firebase - PullRequest
0 голосов
/ 11 января 2020

Я пишу бэкэнд-функцию, используя Node.JS Express framework. Функция состоит в том, чтобы загрузить файл в Firebase Storage. Это мой контроллер с именем fileController. js

(function () {
    var router = require('express').Router(),
        middleware = require('../../util/middleware'),
        os = require('os'),
        path = require('path'),
        Busboy = require('busboy'),
        fs = require('fs'),
        UUID = require("uuid-v4");
    const functions = require('firebase-functions');
    const { Storage } = require('@google-cloud/storage');

    router.post('/svc/uploadFile', middleware.isValidUser, functions.https.onRequest((req, res) => {
        const gcconfig = {
            projectId: '****',
            keyFilename: '****'
        }
        const gcs = new Storage(gcconfig);
        if (req.method !== "POST") {
            return res.status(500).json({ message: "Not allowed" });
        }
        const busboy = new Busboy({ headers: req.headers });
        let uploadData = null;
        let uuid = UUID();

        busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
            const filepath = path.join(os.tmpdir(), uuid + filename);
            uploadData = { file: filepath, type: mimetype };
            file.pipe(fs.createWriteStream(filepath));
        });

        busboy.on('finish', () => {
            const bucket = gcs.bucket('****');
            bucket.upload(uploadData.file, {
                uploadType: 'media',
                metadata: {
                    metadata: {
                        contentType: uploadData.type,
                        firebaseStorageDownloadTokens: uuid
                    }
                }
            }).then((data) => {
                let file = data[0];
                return res.status(200).json({ fileLocation: **** });
            }).catch((err) => {
                res.status(500).json({
                    error: err
                });
            });
        });
        return req.pipe(busboy);
    }));
    module.exports = router;
}());

Это мой индекс. js file

(function () {
    var express = require('express'),
        app = express(),
        bodyParser = require('body-parser'),
        mongoose = require('mongoose'),
        port = 3000,
        cors = require('cors'),
        passport = require('passport'),
        passportCfg = require('./src/config/passport'),
        session = require('express-session'),
        flash = require('connect-flash');

    const functions = require('firebase-functions');
    const MongoStore = require('connect-mongo')(session);
    passportCfg(passport);
    // connect to mongoose
    mongoose.connect('****', { useNewUrlParser: true });
    mongoose.set('useNewUrlParser', true);
    mongoose.set('useFindAndModify', false);
    mongoose.set('useCreateIndex', true);
    var db = mongoose.connection;
    //Bind connection to error event (to get notification of connection errors)
    db.on('error', console.error.bind(console, 'MongoDB connection error:'));
    app.use(cors({
        origin: ['httt://localhost:4200', 'http://127.0.0.1:4200'],
        credentials: true
    }));
    app.use(bodyParser.json());
    app.use(session({
        name: '****',
        secret: '****',
        saveUninitialized: false,
        resave: false,
        cookie: {
            maxAge: 1000 * 60 * 3000,
            httpOnly: false,
            secure: false
        },
        store: new MongoStore({ mongooseConnection: mongoose.connection })
    }));
    app.use(passport.initialize());
    app.use(passport.session());
    app.use(flash());
    app.use(require('./src/controller/fileController'));
    app.listen(port);
    console.log('Running on port:' + port);
    exports.app = functions.https.onRequest(app);
}());

Это зависимость в пакете. json file

 "engines": {
    "node": "8"
  },
"dependencies": {
    "firebase-admin": "^8.6.0",
    "firebase-functions": "^3.3.0",
    "bcryptjs": "^2.4.3",
    "body-parser": "*",
    "connect-flash": "^0.1.1",
    "connect-mongo": "^3.0.0",
    "cors": "^2.8.5",
    "express": "*",
    "express-session": "^1.17.0",
    "http-status": "^1.4.0",
    "moment": "^2.24.0",
    "mongoose": "^5.8.4",
    "passport": "^0.4.0",
    "passport-facebook": "^3.0.0",
    "passport-google-oauth": "^2.0.0",
    "passport-local": "^1.0.0",
    "request": "^2.88.0",
    "rxjs": "^6.5.3",
    "@google-cloud/storage": "^2.4.2",
    "busboy": "^0.3.0",
    "child-process-promise": "^2.2.1",
    "os": "^0.1.1",
    "path": "^0.12.7",
    "uuid-v4": "^0.1.0"
  }

Я устанавливаю firebase-tools , затем запускаю локально, сначала выполняя команду firebase serve , и она прекрасно работает в локальной системе. Затем я выполняю развертывание в firebase с помощью команды firebase deploy с механизмом узла 8.

Локально, busboy.on ('file') будет вызываться и настраивать переменную Сначала uploadData , затем busboy.on ('fini sh') будет использовать его внутри. Но в Google Firebase внутри события busboy.on ('fini sh') uploadData всегда не определено.

Это из-за того, что служба REST не имеет состояния?

1 Ответ

1 голос
/ 15 января 2020

Мне удалось исправить мою проблему. Спасибо всем в этой теме https://github.com/expressjs/multer/issues/411, особенно комментарий https://github.com/serhiipalash

const cors = require('cors')
const bodyParser = require('body-parser')
const Busboy = require('busboy')
const getRawBody = require('raw-body')
const contentType = require('content-type')

app.post(
  '/post-tweet',
  [
    // middlewares

    cors({ origin: true }),

    bodyParser.json(),

    bodyParser.urlencoded({
      extended: true,
    }),

    (req, res, next) => {
      if (
        req.rawBody === undefined &&
        req.method === 'POST' &&
        req.headers['content-type'].startsWith('multipart/form-data')
      ) {
        getRawBody(
          req,
          {
            length: req.headers['content-length'],
            limit: '10mb',
            encoding: contentType.parse(req).parameters.charset,
          },
          function(err, string) {
            if (err) return next(err)
            req.rawBody = string
            next()
          }
        )
      } else {
        next()
      }
    },

    (req, res, next) => {
      if (
        req.method === 'POST' &&
        req.headers['content-type'].startsWith('multipart/form-data')
      ) {
        const busboy = new Busboy({
          headers: req.headers,
        })

        var fileBuffer = new Buffer('')

        busboy.on('file', (fieldname, file, filename, encoding, mimetype) => {
          file.on('data', data => {
            fileBuffer = Buffer.concat([fileBuffer, data])
          })

          file.on('end', () => {
            const file_object = {
              fieldname,
              originalname: filename,
              encoding,
              mimetype,
              buffer: fileBuffer,
            }

            req.file = file_object
          })
        })

        req.data = {}

        busboy.on('field', function(
          fieldname,
          val
          // fieldnameTruncated
          // valTruncated
          // encoding
          // mimetype
        ) {
          req.data[fieldname] = val
        })

        busboy.on('finish', function() {
          console.log('Done parsing form!')

          next()
        })

        busboy.end(req.rawBody)
      } else {
        next()
      }
    },
  ],
  function(req, res, next) {
    // request handler
    const file = req.file

    console.log(file)
  }
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...