Node.js Aws Lambda:getObject 到 base64

Cap*_*Mik 6 amazon-s3 node.js aws-lambda

我从这里修改了 zip 函数https://dzone.com/articles/serverless-zipchamp-update-your-zip-files-in-s3-al因为它只能压缩文本而不能压缩图像。

问题出现在代码末尾的函数 base64_encode 中。我可以将 base64 字符串写入控制台,但无法将其返回给调用函数。

欢迎任何帮助。

let AWS = require('aws-sdk');
let JSZip = require("jszip");
let fs = require("fs");
const s3 = new AWS.S3();
let thebase='';


exports.handler = function (event, context, callback) {
    let myzip = event.zip;
    let modified = 0, removed = 0;
    let mypath = event.path;
    let mynewname = event.newname;
    let filename = event.filename;

	//get Zip file
    s3.getObject({
        'Bucket': "tripmasterdata",
        'Key': event.path+'/'+myzip,
       
    }).promise()
        .then(data => {
            let jszip = new JSZip();
            jszip.loadAsync(data.Body).then(zip => {
                // add or remove file
                if (filename !== '') {
                      //here I get the Image to be stored in the zip as base64 encoded string
                      thebase = base64_encode(mypath,filename,thebase);
                      console.log('AD:'+thebase); //<- this is always empty, WHY????
                      zip.file(mynewname, thebase, {createFolders: false,compression: "STORE",base64: true});
                      modified++;
                } else {
                      console.log(`Remove ${filename}`);
                      zip.remove(filename);
                      removed++;
                }

                let tmpzip = `/tmp/${myzip}`
                let tmpPath = `${event.path}`
                //Generating the zip
                console.log(`Writing to temp file ${tmpzip}`);
                zip.generateNodeStream({ streamFiles: true })
                    .pipe(fs.createWriteStream(tmpzip))
                    .on('error', err => callback(err))
                    .on('finish', function () {
                        console.log(`Uploading to ${event.path}`);
                        s3.putObject({
                            "Body": fs.createReadStream(tmpzip),
                            "Bucket": "xxx/"+tmpPath,
                            "Key": myzip,
                            "Metadata": {
                                "Content-Length": String(fs.statSync(tmpzip).size)
                            }
                        })
                            .promise()
                            .then(data => {
                                console.log(`Successfully uploaded ${event.path}`);
                                callback(null, {
                                    modified: modified,
                                    removed: removed
                                });
                            })
                            .catch(err => {
                                callback(err);
                            });
                    });
            })
                .catch(err => {
                    callback(err);
                });
        })
        .catch(err => {
            callback(err);
        });
}
//function that should return my base64 encoded image
function base64_encode(path,file,thebase) {
    var leKey = path+'/'+file;
    var params = {
    'Bucket': "xxx",
        'Key': leKey
    }
   s3.getObject(params, function(error, data) {
        console.log('error: '+error);
     	}).promise().then(data => {
        	thebase = data.Body.toString('base64');
        	console.log('thebase: '+thebase); //<- here I see the base64 encoded string
        	return thebase; //<- does not return thebase
       });
      return thebase; //<- does not return thebase
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*ter 2

这是一个与承诺相关的问题,与函数“return thebase;”中的最后一次调用有关。由于承诺尚未解决,很可能会返回未定义。当函数返回时。我发现使用关键字 async 和 wait 很有用,这确实将代码简化为更具可读性的格式(它使代码扁平化很多)。

function base64_encode(path,file,thebase) {
  var leKey = path+'/'+file;
  var params = {
    'Bucket': "xxx",
    'Key': leKey
  }
  return s3.getObject(params).promise();
}
Run Code Online (Sandbox Code Playgroud)

然后在主函数中你想用 .then() 处理承诺

如果您使用 async/await ,它将如下所示:

async function base64_encode(path,file,thebase) {
  var leKey = path+'/'+file;
  var params = {
    'Bucket': "xxx",
    'Key': leKey
  }
  return s3.getObject(params).promise();
}

let thebase = await base64_encode('stuff');
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助