S3.putObject - 回调永远不会被调用

Posted

技术标签:

【中文标题】S3.putObject - 回调永远不会被调用【英文标题】:S3.putObject - callback never gets called 【发布时间】:2015-07-28 14:12:55 【问题描述】:

我正在尝试将图像上传到 S3,但是当我调用 s3.putObject(params, callback) 时,我的回调永远不会被调用,也不会记录任何错误。

以下是相关代码:

var params = 
  Key: key,
  Body: imageData,
  ContentLength: imageData.byteCount,
  ContentType: contentType,
;
this.s3.putObject(params, function(err, data) 
  console.log('here');
  if (err) 
    callback(err);
    return;
  
  callback(null, key);
);

params 是 Key: 'e2f99bf3a321282cc7dfaef69fe8ca62.jpg', Body: imageData parsed from request using node-multiparty, ContentLength: 27802, ContentType: 'image/jpeg',

我已经验证 this.s3 是有效的,并且 typeof this.s3.putObject 的功能符合预期。

【问题讨论】:

您可能会通过安装并要求 npm 中的 nock 模块获得一些见解,该模块将准确打印出请求的 URL。如果程序挂起等待回调,则可能是防火墙忽略了 TCP 连接尝试。您是否让程序挂起几分钟以查看它是否最终超时并调用回调? 您的程序是否在异步事件可以返回值之前完成执行?请参阅 AWS Lambda 的类似主题:***.com/questions/28449363/… 【参考方案1】:

如果此代码用于 lambda 函数,您需要在 putObject 的回调函数中添加 context.done(),如下所示:

        s3.putObject(params, function(err, data) 
            if (err) console.log(err, err.stack); // an error occurred
            else     console.log(data);           // successful response
            context.done();
        );

这会强制执行等到回调被填充后再退出。 为此,您还需要从主处理程序中删除任何 context.succeed 或 context.done(如果您有的话)。

【讨论】:

在这个......嗯......上下文中什么是“上下文”?它没有在您的代码或原始问题中的任何地方声明。 啊,好点@boutell。我确实假设这个问题是指使用 AWS Lambda,尽管它没有明确说明。我将编辑我的答案以反映这一点。上下文是 Lambda 特定的对象。如果使用 Lambda,则需要在回调函数中调用上下文完成方法(完成、成功、失败)以使其完成。如果这不是 Lambda 代码,则正在使用的程序在回调完成之前完成。 感谢您的澄清!您可能只想写“AWS Lambda”,因为 lambda 函数具有更一般的含义。【参考方案2】:

我在所有 IAM 权利下都得到了完全相同的行为,但在我让它发挥作用之前浪费了一些时间。

如果您的 lambda 函数在 VPC 内运行,您必须为 S3 创建一个端点,如 this article from AWS blog 中所述。

如果您想查看更多详细信息,可以使用以下代码。而不是给回调一个保留对请求的引用并基本上观察它的事件(参见S3.putObject和AWS.Request的文档)。

var obj = s3.putObject(params);
obj.on('validate',             (...args)=>args.unshift('validate');             console.log(...args);)
   .on('build',                (...args)=>args.unshift('build');                console.log(...args);)
   .on('sign',                 (...args)=>args.unshift('sign');                 console.log(...args);)
   .on('send',                 (...args)=>args.unshift('send');                 console.log(...args);)
   .on('retry',                (...args)=>args.unshift('retry');                console.log(...args);)
   .on('extractError',         (...args)=>args.unshift('extractError');         console.log(...args);)
   .on('extractData',          (...args)=>args.unshift('extractData');          console.log(...args);)
   .on('success',              (...args)=>args.unshift('success');              console.log(...args);)
   .on('error',                (...args)=>args.unshift('error');                console.log(...args);)
   .on('complete',             (...args)=>args.unshift('complete');             console.log(...args);)
   .on('httpHeaders',          (...args)=>args.unshift('httpHeaders');          console.log(...args);)
   .on('httpData',             (...args)=>args.unshift('httpData');             console.log(...args);)
   .on('httpUploadProgress',   (...args)=>args.unshift('httpUploadProgress');   console.log(...args);)
   .on('httpDownloadProgress', (...args)=>args.unshift('httpDownloadProgress'); console.log(...args);)
   .on('httpError',            (...args)=>args.unshift('httpError');            console.log(...args);)
   .on('httpDone',             (...args)=>args.unshift('httpDone');             console.log(...args);)
   .send();

通过这样做,我看到底层 HTTP 请求正在尝试访问存储桶的公共 url,这在 VPC 中是不可能的,除非你有端点:)。

这里还有另一篇关于从 VPC 访问 AWS 资源的帖子,同样来自 AWS blog。

【讨论】:

以上是关于S3.putObject - 回调永远不会被调用的主要内容,如果未能解决你的问题,请参考以下文章

解析:[PFFacebookUtils reauthorizeUser:] 回调永远不会被调用

OsX 中 USB HID API 的回调永远不会被游戏手柄或其他任何东西调用

Vue 计算属性函数永远不会被调用

从不同线程调用时,WCF Duplex 回调方法永远不会执行

Facebook SDK 登录回调永远不会被称为 android

.then() 函数永远不会为调用区块链而运行