114 votes

Ajouter des données à un objet S3

Disons que j'ai une machine sur laquelle je veux pouvoir écrire dans un certain fichier journal stocké sur un seau S3.

La machine doit donc avoir la capacité d'écrire dans ce bac, mais je ne veux pas qu'elle ait la capacité d'écraser ou de supprimer les fichiers de ce bac (y compris celui dans lequel je veux qu'elle écrive).

En gros, je veux que ma machine puisse seulement ajouter des données à ce fichier journal, sans le remplacer ou le télécharger.

Existe-t-il un moyen de configurer mon S3 pour qu'il fonctionne de cette manière ? Peut-être y a-t-il une politique IAM que je peux y attacher pour qu'il fonctionne comme je le souhaite ?

0 votes

Vous ne pouvez pas modifier les objets dans S3. Pourriez-vous simplement ajouter un nouveau fichier journal ? Ce serait un meilleur modèle et cela prendrait en charge plusieurs clients simultanés.

0 votes

@jarmod Oui, j'y ai pensé, mais le problème est que si un attaquant réussit à accéder à mon serveur, il aura la possibilité de supprimer le fichier local stocké sur celui-ci, avant qu'il ne soit envoyé vers le seau S3 (ce qui, disons, se produit à la fin de la journée).

0 votes

Vous pouvez également jeter un coup d'œil aux journaux de CloudWatch. Laissez-le gérer la complexité de la collecte et du stockage de vos journaux, fournir des facilités de recherche, des politiques de conservation et vous permettre de générer des alertes basées sur des métriques que vous pouvez personnaliser pour vos journaux.

169voto

duskwuff Points 69245

Malheureusement, vous ne pouvez pas.

S3 n'a pas d'opération "append". * Une fois qu'un objet a été téléchargé, il n'y a aucun moyen de le modifier sur place ; votre seule option est de télécharger un nouvel objet pour le remplacer, ce qui ne répond pas à vos exigences.

* : Oui, je sais que ce post date d'il y a quelques années. Mais il est toujours d'actualité.

0 votes

Puis-je savoir si l'utilisation de Multipart Upload permet d'atteindre cet objectif ?

4 votes

Le téléchargement multipartite vous permettra d'obtenir les données dans S3 sans télécharger l'objet original, mais il ne vous permettra pas d'écraser l'objet original directement. Voir par exemple docs.aws.amazon.com/AmazonS3/latest/API/ Vous pouvez alors supprimer l'ancien objet et renommer le nouveau. Ce n'est toutefois pas ce que demande la question.

2 votes

Je pense que l'utilisation de Multipart Upload pourrait fonctionner. Toutes vos parties sont des segments séquentiels du même fichier. Si la partie réussit à être téléchargée, vous pouvez éventuellement valider le téléchargement pour pouvoir lire le fichier. Donc, aussi longtemps que vous n'avez pas besoin de lire le contenu du fichier, vous pouvez l'annexer en utilisant le même téléchargement multipart.

27voto

Sridhar-Sarnobat Points 965

Comme l'indique la réponse acceptée, vous ne pouvez pas. La meilleure solution que je connaisse est d'utiliser :

AWS Kinesis Firehose

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

Leur exemple de code a l'air compliqué mais le vôtre peut être très simple. Vous continuez à effectuer des opérations PUT (ou BATCH PUT) sur un flux de livraison Kinesis Firehose dans votre application (à l'aide du SDK AWS), et vous configurez le flux de livraison Kinesis Firehose pour envoyer vos données diffusées vers un seau AWS S3 de votre choix (dans la console AWS Kinesis Firehose).

enter image description here

Ce n'est toujours pas aussi pratique que >> à partir de la ligne de commande Linux, parce qu'une fois que vous avez créé un fichier sur S3, vous devez à nouveau vous occuper du téléchargement, de l'ajout et du transfert du nouveau fichier, mais vous ne devez le faire qu'une fois par lot de lignes plutôt que pour chaque ligne de données, de sorte que vous n'avez pas à vous soucier de frais énormes en raison du volume des opérations d'ajout. C'est peut-être possible, mais je ne vois pas comment le faire à partir de la console.

10 votes

Notez que cette opération est soumise à une durée maximale (900 secondes depuis la création du fichier) ou à une taille maximale (128 mégaoctets). En d'autres termes, le flux de données de Kinesis s'ajoutera au même fichier S3 jusqu'à ce qu'il atteigne l'une de ces limites : docs.aws.amazon.com/firehose/latest/dev/create-configure.html

1 votes

Pouvez-vous utiliser un seul fichier S3 comme sortie sur le Firehose ? Cela semble un peu compliqué de devoir fusionner plusieurs fichiers dans un seau S3.

1 votes

Malheureusement non. Moi aussi, j'aimerais qu'il y ait une meilleure solution.

12voto

Bharthan Points 562

Les objets sur S3 ne sont pas appendables. Vous avez 2 solutions dans ce cas :

  1. copier toutes les données S3 dans un nouvel objet, ajouter le nouveau contenu et réécrire dans 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. La deuxième option consiste à utiliser Kinesis Firehose. C'est assez simple. Vous devez créer votre flux de livraison Firehose et lier la destination au seau S3. C'est tout !
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
    }); 
}

0 votes

Pouvez-vous utiliser un seul fichier S3 comme sortie ?

3voto

wanghq Points 744

Si quelqu'un souhaite ajouter des données à un objet avec un service de type S3, l'OSS (Object Storage Service) d'Alibaba Cloud le supporte nativement .

OSS propose le téléchargement d'append (via l'API AppendObject), qui vous permet d'ajouter directement du contenu à la fin d'un objet. Les objets téléchargés en utilisant cette méthode sont des objets appendables, tandis que les objets téléchargés en utilisant d'autres méthodes sont des objets normaux. Les données ajoutées sont immédiatement lisibles.

1voto

Neeraj Kumar Points 1858

J'ai eu le même problème et voici ce que j'avais demandé

Comment ajouter des données dans un fichier à l'aide d'AWS Lambda ?

Voici ce que j'ai trouvé pour résoudre le problème ci-dessus :

Utilisez getObject pour récupérer le fichier existant.

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

Fonction d'écriture pour ajouter dans le fichier

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

J'espère que cela aidera !

13 votes

Votre writeToS3 écrasera un fichier, et non l'ajoutera.

0 votes

@duskwuff-inactive- d'accord, et aussi il souffre de conditions de course si deux méthodes essayent de travailler sur le même objet, mais ce n'est pas vraiment différent des langages qui ont des chaînes ou des types immuables -- vous simulez un ajout en retournant/réécrivant avec un nouvel objet.

0 votes

Cette méthode est utile car elle présente l'avantage de ne pas consommer de bande passante supplémentaire si l'apposition des données se fait en dehors du réseau AWS.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X