将数据附加到 S3 对象

Append data to an S3 object

假设我有一台机器,我希望能够写入存储在 S3 存储桶中的特定日志文件。

因此,机器需要具有写入该存储桶的能力,但是,我不希望它具有覆盖或删除该存储桶中任何文件(包括我希望它写入的文件)的能力.

所以基本上,我希望我的机器能够只将数据附加到该日志文件,而不覆盖它或下载它。

有没有办法配置我的 S3 以那样工作?也许有一些我可以附加到它的 IAM 政策,所以它会像我想要的那样工作?

很遗憾,你不能。

S3 doesn't have an "append" operation.* 对象一旦上传,就无法修改;你唯一的选择是上传一个新的对象来替换它,这不符合你的要求。

*:是的,我知道这个 post 已经有几年了。不过,它仍然准确。

如已接受的答案所述,您不能。我知道的最佳解决方案是使用:

AWS Kinesis Firehose

https://aws.amazon.com/kinesis/firehose/

他们的 code sample 看起来很复杂,但您的可以非常简单。您继续对应用程序中的 Kinesis Firehose 传输流执行 PUT(或 BATCH PUT)操作(使用 AWS SDK),并配置 Kinesis Firehose 传输流以将流式数据发送到您选择的 AWS S3 存储桶(在AWS Kinesis Firehose 控制台)。

它仍然不如 Linux 命令行中的 >> 方便,因为一旦您在 S3 上创建了一个文件,您就必须再次处理下载、附加和上传新文件文件,但您只需每批行执行一次,而不是对每行数据执行一次,因此您无需担心由于追加操作量而产生的巨额费用。也许可以完成,但我看不到如何从控制台执行此操作。

我遇到了类似的问题,这就是我所问的问题

how to Append data in file using AWS Lambda

这是我解决上述问题的方法:

使用 getObject 从现有文件中检索

   s3.getObject(getParams, function(err, data) {
   if (err) console.log(err, err.stack); // an error occurred
   else{
       console.log(data);           // successful response
       var s3Projects = JSON.parse(data.Body);
       console.log('s3 data==>', s3Projects);
       if(s3Projects.length > 0) {
           projects = s3Projects;
       }   
   }
   projects.push(event);
   writeToS3(); // Calling function to append the data
});

写入函数追加到文件中

   function writeToS3() {
    var putParams = {
      Body: JSON.stringify(projects),
      Bucket: bucketPath, 
      Key: "projects.json",
      ACL: "public-read"
     };

    s3.putObject(putParams, function(err, data) {
       if (err) console.log(err, err.stack); // an error occurred
       else     console.log(data);           // successful response
        callback(null, 'Hello from Lambda');
     });
}

希望对您有所帮助!!

S3 上的对象不可追加。在这种情况下,您有 2 个解决方案:

  1. 将所有 S3 数据复制到新对象,附加新内容并写回 S3。
function writeToS3(input) {
    var content;
    var getParams = {
        Bucket: 'myBucket', 
        Key: "myKey"
    };

    s3.getObject(getParams, function(err, data) {
        if (err) console.log(err, err.stack);
        else {
            content = new Buffer(data.Body).toString("utf8");
            content = content + '\n' + new Date() + '\t' + input;
            var putParams = {
                Body: content,
                Bucket: 'myBucket', 
                Key: "myKey",
                ACL: "public-read"
             };

            s3.putObject(putParams, function(err, data) {
                if (err) console.log(err, err.stack); // an error occurred
                else     {
                    console.log(data);           // successful response
                }
             });
        }
    });  
}
  1. 第二种选择是使用 Kinesis Firehose。这相当简单。您需要创建流水线传输流和 link S3 存储桶的目标。就是这样!
function writeToS3(input) {
    var content = "\n" + new Date() + "\t" + input;
    var params = {
      DeliveryStreamName: 'myDeliveryStream', /* required */
      Record: { /* required */
        Data: new Buffer(content) || 'STRING_VALUE' /* Strings will be Base-64 encoded on your behalf */ /* required */
      }
    };

    firehose.putRecord(params, function(err, data) {
      if (err) console.log(err, err.stack); // an error occurred
      else     console.log(data);           // successful response
    }); 
}

正如之前其他人所说,S3 对象不可追加。
但是,另一种解决方案是写入 CloudWatch 日志,然后 export the logs you want to S3。这也可以防止访问您的服务器的任何攻击者从您的 S3 存储桶中删除,因为 Lambda 不需要任何 S3 权限。

如果有人想使用类似 S3 的服务将数据附加到对象,阿里云 OSS(对象存储服务)supports this natively

OSS provides append upload (through the AppendObject API), which allows you to directly append content to the end of an object. Objects uploaded by using this method are appendable objects, whereas objects uploaded by using other methods are normal objects. The appended data is instantly readable.

S3 bucket 不允许你附加现有的对象,可以使用的方法是先使用 get 方法从 S3 bucket 中获取数据,然后添加你想要附加的新数据。在本地然后将其推回 S3 存储桶。

因为,无法附加到现有的 S3 对象。您需要将其替换为附加了数据的新对象。这意味着每次向其附加新条目时,您都需要上传整个对象(日志文件)。这不会很有效。

您可以将日志条目发送到 SQS 队列,当队列大小达到设定数量时,您可以将日志消息一起批处理并作为一个对象添加到您的 S3 存储桶中。这仍然不能满足您追加到单个对象的要求

您可以:

  1. 设置分段上传
  2. 调用 UploadPartCopy 将现有的 s3 对象指定为源
  3. 使用您要追加的数据调用 UploadPart
  4. 关闭分段上传。

有很多限制,例如您现有的对象必须大于 5MB(但是,如果较小,则在大多数情况下将其复制到客户端应该足够快) 它不如直接附加好,但至少你不需要将数据从 aws 来回复制到本地机器。