Додайте дані до об’єкта S3


91

Скажімо, у мене є машина, яку я хочу мати можливість записувати в певний файл журналу, що зберігається в сегменті S3.

Отже, машина повинна мати можливості запису в це сегмент, але, я не хочу, щоб вона мала можливість перезаписувати або видаляти будь-які файли в цьому сегменті (включаючи той, у який я хочу, щоб він писав).

Отже, я хочу, щоб моя машина могла лише додавати дані до цього журналу, не перевизначаючи їх і не завантажуючи.

Чи є спосіб налаштувати мій S3 так працювати? Можливо, є якась політика IAM, яку я можу додати до неї, щоб вона працювала так, як я хочу?


Ви не можете змінювати об'єкти в S3. Не могли б ви просто додати новий файл журналу? Це була б краща модель і підтримувала б декілька одночасних клієнтів.
jarmod

@jarmod Так, я думав про це, але проблема в тому, що якщо зловмисникові вдасться отримати доступ до мого сервера, він матиме можливість видалити локальний файл, що зберігається на ньому, перед тим, як його було відправлено в сегмент S3 (що, скажімо, трапляється в кінці дня).
Теодор

Можливо, ви також захочете поглянути журнали CloudWatch. Нехай він управляє складністю збору та зберігання ваших журналів, надає засоби пошуку, політики збереження та дозволяє генерувати сповіщення на основі показників, які ви можете налаштувати для своїх журналів.
jarmod

1
Ви також можете заглянути в Google BigQuery. Ви можете використовувати його для вирішення своєї проблеми.
Daniel777,

Відповіді:


133

На жаль, ви не можете.

S3 не має операції "додавання". * Після завантаження об’єкта неможливо змінити його на місці; ваш єдиний варіант - завантажити новий об’єкт на заміну, який не відповідає вашим вимогам.

*: Так, я знаю, що цій публікації пару років. Однак це все ще точно.


Чи можу я знати, чи можна досягти цього за допомогою багатозавантаженого завантаження?
Анджалі,

1
Завантаження кількома деталями дозволить вам отримати дані на S3 без завантаження оригінального об'єкта, але це не дозволить вам перезаписати оригінальний об'єкт безпосередньо. Див., Наприклад, docs.aws.amazon.com/AmazonS3/latest/API/ ... Потім ви можете видалити старий об’єкт / перейменувати новий. Однак це не те, що задає питання.
MikeGM

Я думаю, що використання багаточастинного завантаження може насправді спрацювати. Усі ваші частини є послідовними сегментами одного файлу. Якщо частину вдається завантажити, ви можете врешті-решт здійснити завантаження, щоб мати можливість прочитати файл. Отже, поки вам не потрібно читати вміст файлу, ви можете додати додаток до того самого багаточастинного завантаження.
cerebrotecnologico

@cerebrotecnologico Я все ще не думаю, що він відповідає вимогам OP. Мені не відомо, як я можу обмежити користувача S3 виконувати багаточастинні завантаження, які додаються до об’єкта, - якщо вони можуть виконувати багаточасткове завантаження, вони можуть завантажувати будь-який вміст, який хочуть.
duskwuff -active-

16

Як стверджує прийнята відповідь, ви не можете. Найкраще рішення, яке мені відомо, - використовувати:

AWS Kinesis Firehose

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

Їх зразок коду виглядає складним, але ваш може бути дуже простим. Ви продовжуєте виконувати операції PUT (або BATCH PUT) над потоком доставки Kinesis Firehose у вашій програмі (за допомогою AWS SDK), і ви налаштовуєте потік доставки Kinesis Firehose для надсилання ваших потокових даних у відрі AWS S3 на ваш вибір (у Консоль AWS Kinesis Firehose).

введіть тут опис зображення

Це все ще не так зручно, як >>з командного рядка Linux, тому що, як тільки ви створили файл на S3, вам знову доведеться мати справу із завантаженням, додаванням та завантаженням нового файлу, але це потрібно робити лише один раз на партію рядків, а не ніж для кожного рядка даних, тому вам не потрібно турбуватися про величезні витрати через обсяг операцій додавання. Можливо, це можна зробити, але я не бачу, як це зробити з консолі.


8
Зверніть увагу, що для цього існує або максимальний час (900 секунд з моменту створення файлу), або максимальний розмір (розмір файлу 128 МБ) - тобто, Kinesis firehose додаватиметься до того самого файлу S3, поки не досягне жодного з цих обмежень: docs.aws .amazon.com / firehose / latest / dev / create-configure.html
Ярон Будовський

Чи можете ви використовувати один файл S3 як вихід на Firehose? Звучить дещо безладно, якщо об’єднувати кілька файлів у відрі S3.
Йон Траусті Арасон

1
На жаль, немає. Я теж хотів би, щоб було краще рішення.
Шрідхар Сарнобат

Так, це прикро. Мене здебільшого турбує стан перегонів, якщо я вручну завантажую та додаю записи до одного об’єкта S3. Я думав про те, щоб додати записи до SQS, а потім використати якусь логіку з SNS + Lambda для опитування SQS, а потім написати нові записи в об'єкт S3.
Йон Траусті Арасон,

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. Другий варіант - використовувати Kinesis Firehose. Це досить просто. Вам потрібно створити свій потік доставки firehose і зв’язати пункт призначення з сегментом 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 як вихід?
Йон Траусті Арасон

1

Як інші вже заявляли раніше, об'єкти S3 не можна додавати.
Однак іншим рішенням було б записати журнали CloudWatch, а потім експортувати журнали, які ви хочете, у S3 . Це також завадить будь-яким зловмисникам, які отримують доступ до вашого сервера, видаляти з вашого сегмента S3, оскільки Lambda не вимагатиме дозволів на S3.


1

У випадку, якщо хтось хоче додати дані до об’єкта із послугою, подібною до S3, Alibaba Cloud OSS (служба зберігання об’єктів) підтримує це спочатку .

OSS забезпечує завантаження додатків (через API AppendObject), що дозволяє безпосередньо додавати вміст до кінця об’єкта. Об'єкти, завантажені за допомогою цього методу, є об'єктами, що додаються, тоді як об'єкти, завантажені за допомогою інших методів, є звичайними об'єктами. Додані дані можна миттєво прочитати.


-1

У мене була подібна проблема, і я про це просив

Як додати дані у файл за допомогою 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');
     });
}

Сподіваюся, ця допомога !!


13
Ваша writeToS3функція перезапише файл, а не додасть його.
сутінки-неактивні-

@ duskwuff-inactive- погодився, а також він страждає від расових умов, якщо два методи намагаються працювати на одному і тому ж об'єкті, але це насправді не відрізняється від мов, які мають незмінні рядки або типи - ви імітуєте додавання, повертаючи / перезаписуючи новий об’єкт.
fatal_error
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.