javascript - Firebase(multer, Busboy) के लिए क्लाउड फ़ंक्शंस पर एक्सप्रेस का उपयोग करके HTTP फ़ाइल अपलोड कैसे करें




express google-cloud-functions (5)

आधिकारिक क्लाउड फ़ंक्शन टीम के उत्तर में जोड़ने के लिए, आप निम्नलिखित करके स्थानीय रूप से इस व्यवहार का अनुकरण कर सकते हैं (इस मिडलवेयर को उनके द्वारा पोस्ट किए गए बसब्वॉय कोड से अधिक जोड़ें, जाहिर है)

const getRawBody = require('raw-body');
const contentType = require('content-type');

app.use(function(req, res, next){
    if(req.rawBody === undefined && req.method === 'POST' && req.headers['content-type'] !== undefined && 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();
    }
});

मैं क्लाउड फ़ंक्शंस में एक फ़ाइल अपलोड करने की कोशिश कर रहा हूं, वहां अनुरोधों को संभालने के लिए एक्सप्रेस का उपयोग कर रहा हूं, लेकिन मैं सफल नहीं हो रहा हूं। मैंने एक संस्करण बनाया जो स्थानीय स्तर पर काम करता है:

सर्वर के जे.एस.

const express = require('express');
const cors = require('cors');
const fileUpload = require('express-fileupload');

const app = express();
app.use(fileUpload());
app.use(cors());

app.post('/upload', (req, res) => {
    res.send('files: ' + Object.keys(req.files).join(', '));
});

ग्राहकों की जे.एस.

const formData = new FormData();
Array.from(this.$refs.fileSelect.files).forEach((file, index) => {
    formData.append('sample' + index, file, 'sample');
});

axios.post(
    url,
    formData, 
    {
        headers: { 'Content-Type': 'multipart/form-data' },
    }
);

क्लाउड फ़ंक्शंस में तैनात होने पर यह वही कोड टूटने लगता है, जहां req.files अपरिभाषित होते हैं। क्या किसी को कुछ भी पता नहीं है कि यहां क्या हो रहा है?

EDIT I में भी multer का उपयोग किया गया multer , जो स्थानीय स्तर पर ठीक काम करता था, लेकिन एक बार क्लाउड फ़ंक्शंस में अपलोड करने के बाद, यह मुझे एक खाली सरणी (समान क्लाइंट कोड) मिला:

const app = express();
const upload = multer();
app.use(cors());

app.post('/upload', upload.any(), (req, res) => {
    res.send(JSON.stringify(req.files));
});

इस धागे पर सभी की मदद के लिए धन्यवाद। मैंने हर संभव संयोजन और इन सभी विभिन्न पुस्तकालयों की कोशिश में एक पूरा दिन बर्बाद कर दिया ... केवल अन्य सभी विकल्पों को समाप्त करने के बाद इसे खोजने के लिए।

टाइपस्क्रिप्ट और मिडलवेयर सक्षम स्क्रिप्ट बनाने के लिए ऊपर दिए गए कुछ समाधानों का संयोजन:

https://gist.github.com/jasonbyrne/8dcd15701f686a4703a72f13e3f800c0


मैं कुछ दिनों से एक ही समस्या से जूझ रहा था, पता चला कि फायरबेस टीम ने मल्टीकार्ट / फॉर्म-डेटा के कच्चे शरीर को उनके मिडलवेयर के साथ req.body में डाल दिया है। यदि आप कंसोल की कोशिश करते हैं। (req.body.toString ()) मुलर के साथ आपके अनुरोध को संसाधित करने के बाद, आप अपना डेटा देखेंगे। चूंकि multer एक नया req.body ऑब्जेक्ट बनाता है जो परिणामी req को ओवरराइड कर रहा है, डेटा चला गया है और हम प्राप्त कर सकते हैं एक खाली req.body है। उम्मीद है कि फायरबेस टीम जल्द ही इसे ठीक कर सकती है।


मैं ब्रायन और डौग की प्रतिक्रिया दोनों को संयोजित करने में सक्षम था। यहाँ मेरा मिडलवेयर है जो अंत में mqter में req.files की नकल कर रहा है ताकि आपके कोड के बाकी हिस्सों में कोई परिवर्तन न हो।

module.exports = (path, app) => {
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
app.use((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()
    }
})

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

        busboy.on('field', (fieldname, value) => {
            req.body[fieldname] = value
        })

        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.files.file.push(file_object)
            })
        })

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


        busboy.end(req.rawBody)
        req.pipe(busboy)
    } else {
        next()
    }
})}

ऊपर दिए गए उत्तर के लिए धन्यवाद, मैंने इसके लिए एक npm मॉड्यूल बनाया है ( github )

यह Google क्लाउड फ़ंक्शंस के साथ काम करता है, बस इसे स्थापित करें ( npm install --save express-multipart-file-parser ) और इस तरह उपयोग करें:

const fileMiddleware = require('express-multipart-file-parser')

...
app.use(fileMiddleware)
...

app.post('/file', (req, res) => {
  const {
    fieldname,
    filename,
    encoding,
    mimetype,
    buffer,
  } = req.files[0]
  ...
})




google-cloud-functions