错误:在Firebase Cloud函数中使用大数据时读取ECONNRESET

时间:2017-11-08 09:27:09

标签: node.js facebook firebase google-cloud-functions

我执行了以下任务,在最初几个月的用户注册过程中,我们没有保存Firebase云存储中的用户图像,并获取了从Facebook收到的链接。现在面临的问题是图像的某些链接已经过期。因此,我决定制作云功能并将其作为一个脚本运行一次,以便它通过只有一个图像链接的用户(这意味着这是从facebook收到的第一个链接), facebook用户ID并请求当前个人资料图片。我从Firebase获得了一个给定用户的json文件,然后我分别为每个用户获取链接,如果用户被删除,那么我在一个单独的catch中处理这个错误,这样它就不会停止其他promises的工作。但是在运行这个云功能之后,我遇到了这个错误,因为对于几乎所有用户来说这个操作都没有成功。即使我将云功能的内存大小增加到2千兆字节。请告诉我如何修复它?

{ Error: read ECONNRESET
    at exports._errnoException (util.js:1018:11)
    at TLSWrap.onread (net.js:568:26) code: 'ECONNRESET', errno: 'ECONNRESET', syscall: 'read' }

我的功能

const functions = require('firebase-functions');
const admin = require('firebase-admin');
const account_file = require('../account_file.json');
var FB = require('fb');
const path = require('path');
const imageDownloader = require('image-downloader');
const os = require('os');
const shortid = require('shortid');
const imageManager = require('../../lib/Images/image-manager.js');

module.exports = functions.https.onRequest((req, res) => {
    const token = req.header('X-Auth-Token');

    var errorsCount = 0;

    return admin.auth().verifyIdToken(token)
        .then(function(decodedToken) {
            const adminID = decodedToken.uid;
            console.log('adminID is', adminID);

            const users = account_file['users'];

            var fixPhotoPromises = [];

            users.forEach(function(user) {
                const userID = user['localId']; 
                const fixPhotoPromise = fixPhoto(userID).catch(error => {
                    console.log(error);
                    errorsCount += 1;
                });
                fixPhotoPromises.push(fixPhotoPromise);
            });
            return Promise.all(fixPhotoPromises);
        }).then(results => {
            console.log('results.length', results.length, 'errorsCount', errorsCount);
            console.log('success all operations');
            const successJSON = {};
            successJSON["message"] = "Success operation";
            return res.status(200).send(successJSON);
        }).catch(error => {
            console.log(error);
            const errorJSON = {};
            errorJSON["error"] = error;
            return res.status(error.code).send(errorJSON);
        });
});

function fixPhoto(userID) {
    var authUser = {};
    var filename = '';
    return new Promise((resolve, reject) => {

        return admin.auth().getUser(userID)
            .then(userModel => {
                const user = userModel.toJSON();
                const facebookID = user['providerData'][0]['uid'];
                const userID = user['uid'];
                authUser = {'userID' : userID, 'facebookID' : facebookID};

                const userImagesPromise = admin.database().ref()
                    .child('userImages')
                    .child(userID)
                    .once('value');
                return Promise.all([userImagesPromise])
            }).then(results => {
                const userImagesSnap = results[0];
                if (userImagesSnap.val() !== null && userImagesSnap.val() !== undefined) {
                    const userProfileImagesDict = userImagesSnap.val()['userProfileImages'];
                    const keys = Object.keys(userProfileImagesDict);
                    var userProfileImages = [];
                    keys.forEach(function(key){
                        const userProfileImage = userProfileImagesDict[key];
                        userProfileImages.push(userProfileImage);
                    });
                    if (userProfileImages.length > 1) {
                        const status = 'user has more than one image';
                        return resolve(status);
                    }
                }
                const facebookAppID = functions.config().facebook.appid;
                const facebookAppSecret = functions.config().facebook.appsecret;

                const facebookAccessPromise = FB.api('oauth/access_token', {
                    client_id: facebookAppID,
                    client_secret: facebookAppSecret,
                    grant_type: 'client_credentials'
                });
                return Promise.all([facebookAccessPromise]);
            }).then(results => {
                const facebookResult = results[0];
                const facebookAccessToken = facebookResult['access_token'];

                const profileImageURL = 'https://graph.facebook.com/' + authUser.facebookID + '/picture?width=9999&access_token=' + facebookAccessToken;

                const shortID = shortid.generate() + shortid.generate() + shortid.generate();
                filename = shortID + ".jpg";
                const tempLocalFile = path.join(os.tmpdir(), filename);

                const options = {
                    url: profileImageURL,
                    dest: tempLocalFile                 // Save to /path/to/dest/image.jpg
                };

                const imageDownloaderPromise = imageDownloader.image(options);

                return Promise.all([imageDownloaderPromise])
            }).then(results => {
                const imageDownloaderResult = results[0];
                const userID = authUser.userID;
                const localImagePath = imageDownloaderResult['filename'];

                const imageManagerPromise = imageManager.saveUserImageToCloudStorage(localImagePath, filename, userID);

                return Promise.all([imageManagerPromise]);
            }).then(results => {
                const result = results[0];
                return resolve(result);
            }).catch(function(error) {
                reject(error)
            })
    });
}


exports.saveUserImageToCloudStorage = function saveUserImageToCloudStorage(localImagePath, filename, userID) {
    const bucketName = functions.config().googlecloud.defaultbacketname;
    const bucket = gcs.bucket(bucketName);

    const profileImagePath = path.normalize(path.join('userImages', userID, 'profileImages', filename));
    const profileImageFile = bucket.file(profileImagePath);

    return new Promise((resolve, reject) => {

        bucket.upload(localImagePath, {destination: profileImagePath})
            .then(() => {
                const config = {
                    action: 'read',
                    expires: '03-01-2500'
                };

                const userRefPromise = admin.database().ref()
                    .child('users')
                    .child(userID)
                    .once('value');

                return Promise.all([profileImageFile.getSignedUrl(config), userRefPromise])
            }).then(function(results) {
                const url = results[0][0];
                const userSnap = results[1];
                if (userSnap.val() === null || userSnap.val() === undefined) {
                    return resolve('user was deleted from database');
                }

                const userModel = userSnap.val();
                const userCheckID = userModel['id'];

                if (userCheckID !== userID) {
                    return reject("WARNING userCheckID !== userID");
                }

                // save to database

                const userImagesRef = admin.database().ref().child('userImages')
                    .child(userID)
                    .child('userProfileImages')
                    .push();

                const timeStamp = timestamp.now();
                const imageModelID = userImagesRef.key;
                const userImagesRefPromise = userImagesRef.update({
                    'path': url,
                    'id': imageModelID,
                    'fileName': filename,
                    'timeStamp': timeStamp
                });

                const userRef = admin.database().ref()
                    .child('users')
                    .child(userID)
                    .child('currentProfileImage');
                const userRefPromise = userRef.update({
                    'path': url,
                    'id': imageModelID,
                    'fileName': filename,
                    'timeStamp': timeStamp
                });

                return Promise.all([userImagesRefPromise, userRefPromise]);
            }).then(() => {
                const successJSON = {};
                successJSON["message"] = "Success operation";
                return resolve(successJSON);
            }).catch(function(error) {
                return reject(error);
            });
    });
};

1 个答案:

答案 0 :(得分:0)

我在init google云端存储时添加了此代码,我不再有此错误了。

var gcs = require('@google-cloud/storage')({keyFilename: "service-account-credentials.json"});
gcs.interceptors.push({
    request: function(reqOpts) {
        reqOpts.forever = false
        return reqOpts
    }
});