S3オブジェクトにデータを追加する


91

S3バケットに保存されている特定のログファイルに書き込めるようにしたいマシンがあるとしましょう。

したがって、マシンにはそのバケットへの書き込み機能が必要ですが、そのバケット内のファイル(書き込み先のファイルを含む)を上書きまたは削除する機能は必要ありません。

したがって、基本的には、マシンがデータをオーバーライドしたりダウンロードしたりせずに、そのログファイルにのみデータを追加できるようにしたいのです。

そのように動作するようにS3を設定する方法はありますか?たぶん、私が望むように機能するように添付できるIAMポリシーがいくつかありますか?


S3でオブジェクトを変更することはできません。新しいログファイルを追加していただけませんか?それはより良いモデルであり、複数の同時クライアントをサポートします。
jarmod 2017年

@jarmodええ、私はそれについて考えましたが、問題は、攻撃者が私のサーバーへのアクセスに成功した場合、S3バケットに送信される前にサーバーに保存されているローカルファイルを削除できることです(たとえば、一日の終わりに起こります)。
セオドア

CloudWatchログも確認することをお勧めします。ログの収集と保存の複雑さを管理し、検索機能と保持ポリシーを提供し、ログ用にカスタマイズできるメトリックに基づいてアラートを生成できるようにします。
jarmod 2017年

1
また、GoogleBigQueryもご覧ください。あなたはあなたの問題を解決するためにそれを使うことができます。
Daniel777 2017

回答:


133

残念ながら、できません。

S3には「追加」操作はありません。*オブジェクトがアップロードされると、その場で変更する方法はありません。唯一のオプションは、新しいオブジェクトをアップロードして置き換えることですが、これは要件を満たしていません。

*:はい、この投稿は2、3年前のものです。しかし、それでも正確です。


マルチパートアップロードを使用することで、これを実現できますか?
アンジャリ2017年

1
マルチパートアップロードを使用すると、元のオブジェクトをダウンロードせずにS3にデータを取り込むことができますが、元のオブジェクトを直接上書きすることはできません。たとえば、docs.aws.amazon.com / AmazonS3 / latest / API /を参照してくださいその後、古いオブジェクトを削除するか、新しいオブジェクトの名前を変更できます。しかし、これは質問が求めているものではありません。
MikeGM

マルチパートアップロードの使用は実際に機能すると思います。すべてのパーツは、同じファイルの連続したセグメントです。パーツのアップロードに成功した場合、最終的にアップロードをコミットしてファイルを読み取れるようにすることができます。したがって、ファイルの内容を読み取る必要がない限り、同じマルチパートアップロードを使用して追加することができます。
cerebrotecnologico 2018年

@cerebrotecnologico私はまだそれがOPの要件を満たしているとは思いません。S3ユーザーがオブジェクトに追加するマルチパートアップロードの実行に制限する方法はありません。マルチパートアップロードを実行できる場合は、必要なコンテンツをアップロードできます。
duskwuff -inactive- 2018

16

受け入れられた答えが述べているように、あなたはできません。私が知っている最善の解決策は、以下を使用することです。

AWS Kinesis Firehose

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

彼らのコードサンプルは複雑に見えますが、あなたのコードサンプルは本当に単純なものになり得ます。アプリケーション内のKinesisFirehose配信ストリームに対してPUT(またはBATCH PUT)操作を実行し続け(AWS SDKを使用)、ストリーミングされたデータを選択したAWS S3バケットに送信するようにKinesisFirehose配信ストリームを設定します( AWS Kinesis Firehoseコンソール)。

ここに画像の説明を入力してください

>>Linuxコマンドラインからの場合ほど便利ではありません。S3でファイルを作成したら、新しいファイルのダウンロード、追加、アップロードを再度行う必要がありますが、行のバッチごとに1回だけ実行する必要があるためです。データのすべての行よりも、追加操作の量のために莫大な料金を心配する必要はありません。たぶんそれはできますが、コンソールからそれを行う方法がわかりません。


8
これを行うには、最大時間(ファイル作成から900秒)または最大サイズ(128mbファイルサイズ)のいずれかがあることに注意してください-つまり、Kinesis firehose
Yaron Budowski 2018年

Firehoseの出力として単一のS3ファイルを使用できますか?S3バケット内の複数のファイルをマージする必要があるのは少し面倒に聞こえます。
ジョンTrausti Arason

1
残念だけど違う。私ももっと良い解決策があったらいいのにと思います。
SridharSarnobat19年

ええ、それは残念です。単一のS3オブジェクトにレコードを手動でダウンロードして追加する場合、競合状態が主に心配です。レコードをSQSに追加し、SNS + Lambdaでロジックを使用してSQSをポーリングし、新しいエントリをS3オブジェクトに書き込むことを考えていました。
ジョンTrausti Arason

6

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. 2番目のオプションは、KinesisFirehoseを使用することです。これはかなり簡単です。ファイアホース配信ストリームを作成し、宛先を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ファイルを出力として使用できますか?
ジョンTrausti Arason


1

S3のようなサービスであるAlibabaCloud OSS(オブジェクトストレージサービス)を使用してオブジェクトにデータを追加したい場合 はこれをネイティブにサポートします

OSSは、(AppendObject APIを介して)追加アップロードを提供します。これにより、オブジェクトの末尾にコンテンツを直接追加できます。このメソッドを使用してアップロードされたオブジェクトは追加可能なオブジェクトですが、他のメソッドを使用してアップロードされたオブジェクトは通常のオブジェクトです。追加されたデータはすぐに読み取ることができます。


-1

私は同様の問題を抱えていました、そしてこれは私が尋ねたものです

AWSLambdaを使用してファイルにデータを追加する方法

上記の問題を解決するために私が思いついたものは次のとおりです。

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');
     });
}

この助けを願っています!


13
あなたのwriteToS3関数は、それに追加していないファイルを、上書きされます。
duskwuff -inactive- 2017

@ duskwuff-inactive-同意し、2つのメソッドが同じオブジェクトで機能しようとすると競合状態になりますが、これは不変の文字列または型を持つ言語と実際には違いはありません。新しいオブジェクト。
fatal_error
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.