Me preguntaba si podría configurar una función lambda para AWS, activada cada vez que se carga un nuevo archivo de texto en un depósito s3. En la función, me gustaría obtener el contenido del archivo de texto y procesarlo de alguna manera. Me preguntaba si esto era posible...?
Por ejemplo, si subo foo.txt, con contenido foobarbaz, me gustaría obtener foobarbaz de alguna manera en mi función lambda para poder hacer cosas con él. Sé que puedo obtener metadatos de getObject o un método similar.
¡Gracias!
La clave de objeto de S3 y el nombre del depósito se pasan a su función de Lambda a través del parámetro de evento . Luego puede obtener el objeto de S3 y leer su contenido.
El código básico para recuperar la clave de depósito y objeto del event Lambda es el siguiente:
exports.handler = function(event, context, callback) { const bkt = event.Records[0].s3.bucket.name; const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' ')); };Una vez que tenga el depósito y la clave, puede llamar a getObject para recuperar el objeto:
const AWS = require('aws-sdk'); const s3 = new AWS.S3(); exports.handler = function(event, context, callback) { // Retrieve the bucket & key for the uploaded S3 object that // caused this Lambda function to be triggered const Bucket = event.Records[0].s3.bucket.name; const Key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' ')); // Retrieve the object s3.getObject({ Bucket, Key }, function(err, data) { if (err) { console.log(err, err.stack); callback(err); } else { console.log("Raw text:\n" + data.Body.toString('ascii')); callback(null, null); } }); };Aquí hay un ejemplo de JavaScript actualizado que usa código y promesas de estilo ES6, menos el manejo de errores:
const AWS = require('aws-sdk'); const s3 = new AWS.S3(); exports.handler = async (event, context) => { const Bucket = event.Records[0].s3.bucket.name; const Key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' ')); const data = await s3.getObject({ Bucket, Key }).promise(); console.log("Raw text:\n" + data.Body.toString('ascii')); };Varios carteles han pedido el equivalente en Java, así que aquí hay un ejemplo:
package example; import java.net.URLDecoder; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.S3Event; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3Client; import com.amazonaws.services.s3.event.S3EventNotification.S3EventNotificationRecord; public class S3GetTextBody implements RequestHandler<S3Event, String> { public String handleRequest(S3Event s3event, Context context) { try { S3EventNotificationRecord record = s3event.getRecords().get(0); // Retrieve the bucket & key for the uploaded S3 object that // caused this Lambda function to be triggered String bkt = record.getS3().getBucket().getName(); String key = record.getS3().getObject().getKey().replace('+', ' '); key = URLDecoder.decode(key, "UTF-8"); // Read the source file as text AmazonS3 s3Client = new AmazonS3Client(); String body = s3Client.getObjectAsString(bkt, key); System.out.println("Body: " + body); return "ok"; } catch (Exception e) { System.err.println("Exception: " + e); return "error"; } } }Puede usar data.Body.toString('ascii') para obtener el contenido del archivo de texto, asumiendo que el archivo de texto fue codificado en formato ascii. También puede pasar otros tipos de codificación a la función. Consulte Node-Buffer para obtener más detalles.
Estoy usando la función lambda con un entorno python 3.6. El siguiente código leerá el contenido de un archivo main.txt dentro del depósito my_s3_bucket. Asegúrese de reemplazar el nombre del depósito y el nombre del archivo según sus necesidades.
def lambda_handler(event, context): # TODO implement import boto3 s3 = boto3.client('s3') data = s3.get_object(Bucket='my_s3_bucket', Key='main.txt') contents = data['Body'].read() print(contents)