为什么s3.putObject为nodejs Buffer抛出ERR_INVALID_ARG_TYPE?

时间:2019-08-26 15:05:34

标签: node.js amazon-web-services amazon-s3 aws-lambda babeljs

我在nodejs中编写了一个lambda函数,用于将图像上传到S3存储桶。

在我的第一个lambda函数中,我编写了该内联代码(直接在AWS Lambda编辑器中),并且运行良好。相关代码为:

let decodedImage = Buffer.from(encodedImage, 'base64');
    console.log(decodedImage);
    console.log(typeof decodedImage);
    console.log(Object.prototype.toString.call(decodedImage));

    try {
        await writeToBucket(decodedImage, 'test.png', 'image/png');
    } catch (err) {
        console.log(err);
    } 

async function writeToBucket(data, dbFileId, mimeType) {
    return new Promise((resolve, reject) => {

        var s3 = new AWS.S3();
        const params = {
            Bucket : S3_BUCKET,
            Key : dbFileId,
            Body : data,
            ACL: 'public-read',
            ContentType: mimeType
        }

        s3.putObject(params, function(err, dataString) {
            if (err) {
                reject([503, err]);
            } else {
                resolve();
            }
        });
    });

这三个日志给出:

<Buffer 89 50 4e 47 ... >
object
[object UInt8Array]

因此,如前所述,上述方法工作正常,并且图像已写入存储桶。

现在,我有了第二个Lambda函数,我可以在本地编写该函数,并在使用Webpack构建,压缩和上传后将其上传到Lambda。两个lambda中的代码相同(如上所述),并且控制台输出也相同。但是在第二种情况下,上传失败,并出现以下错误:

{ NetworkingError: The "chunk" argument must be one of type string or Buffer. Received type object
at ClientRequest.end (_http_outgoing.js:690:13)
at features.constructor.writeBody (/var/runtime/node_modules/aws-sdk/lib/http/node.js:137:14)
at features.constructor.handleRequest (/var/runtime/node_modules/aws-sdk/lib/http/node.js:105:12)
at executeSend (/var/runtime/node_modules/aws-sdk/lib/event_listeners.js:342:29)
at Request.SEND (/var/runtime/node_modules/aws-sdk/lib/event_listeners.js:356:9)
at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:102:18)
at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:78:10)
at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:683:14)
at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10)
at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:14:12)
message:
'The "chunk" argument must be one of type string or Buffer. Received type object',
code: 'NetworkingError',
region: 'eu-west-1',
hostname: 's3.eu-west-1.amazonaws.com',
retryable: true,
time: 2019-08-26T14:25:23.006Z } 

据我所知,Body负载确实是Buffer类型,我不知道有什么区别?是Webpack(或Babel)搞砸了吗?还是可以与Nodejs.Buffer有关?我在两个Lambda中都运行Node.js10.x。

我的Webpack设置是这样的:

const path = require('path');
require("@babel/register");
require("@babel/plugin-transform-runtime");

const config = {
    mode: 'development',
  entry: './index.js',

  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'index.js',
    library: 'index',
    libraryTarget: 'commonjs2'
  },
  // Loaders
  module: {
    rules : [
      { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" },
      { test: /\.css$/, use: ['style-loader', 'css-loader']}
    ]
  },
  // Plugins
  plugins: [],
  optimization:{
    minimize: false
  },
  externals: {
    'aws-sdk': 'aws-sdk'
  }
};
// Exports
module.exports = config; 

和package.json依赖项:

"dependencies": {
    "@babel/register": "~7.5.5",
    "@babel/runtime": "~7.5.5",
    "ajv": "~6.10.2",
    "ajv-errors": "~1.0.1",
    "css-loader": "~3.2.0",
    "style-loader": "~1.0.0",
    "uuid": "~3.3.3"
  },
  "devDependencies": {
    "@babel/cli": "~7.5.5",
    "@babel/core": "~7.5.5",
    "@babel/node": "~7.5.5",
    "@babel/plugin-transform-runtime": "~7.5.5",
    "@babel/preset-env": "~7.5.5",
    "aws-sdk": "~2.517.0",
    "babel-loader": "~8.0.6",
    "cross-var-no-babel": "~1.2.0",
    "mocha": "^6.1.4",
    "webpack": "~4.33.0",
    "webpack-cli": "~3.3"
  }

1 个答案:

答案 0 :(得分:1)

此错误令人困惑,因为您的代码确实使用Buffer作为Body,并且没有可见的chunk参数,因此该参数必须在SDK内部。孤立地假设,SDK无法正确处理某些东西,并且抛出异常的时间比预期的要晚得多(例如,不是由于调用s3.putObject()导致的直接结果,而是稍后,在实际的“工作”已经开始。

我有一个na的想法,当尝试优化AWS SDK的大小以进行分发时,我读到了某个关于AWS开发工具包问题的信息……但是我找不到我想要的东西,加上您在{{1 }},所以也许是无关的。

但是我确实找到了 AWS SDK for JavaScript开发者指南(适用于SDK v2)中的Bundling Applications with Webpack

  

您可以使用webpack通过将其指定为配置中的目标来生成在Node.js中运行的包。

     

externals

webpack文档提到了此"...will compile for usage in a Node.js-like environment (uses Node.js require to load chunks and not touch any built in modules like fs or path)"。对于我来说,是否很明显,如果此解释包含一个隐藏的块,说明为什么不包括它会破坏SDK,或者是否发生了其他事情……但指定这似乎是解决问题的原因。

如果我要推测的话,我的猜测是这可以通过禁止包含target: "node" polyfill来实现,而该填充是由webpack添加的。