AWS Lambda
Guia do desenvolvedor

Código de função do Amazon S3 de amostra

O código de amostra está disponível para as seguintes linguagens.

Node.js 8

O código de amostra a seguir recebe uma entrada de evento Amazon S3 e processa a mensagem que ela contém. Ele redimensiona uma imagem no bucket de origem e salva a saída no bucket de destino.

exemplo index.js

var async = require('async'); var AWS = require('aws-sdk'); var gm = require('gm') .subClass({ imageMagick: true }); // Enable ImageMagick integration. var util = require('util'); var MAX_WIDTH = 100; var MAX_HEIGHT = 100; var s3 = new AWS.S3(); exports.handler = function(event, context, callback) { // Read options from the event. console.log("Reading options from event:\n", util.inspect(event, {depth: 5})); var srcBucket = event.Records[0].s3.bucket.name; // Object key may have spaces or unicode non-ASCII characters. var srcKey = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " ")); var dstBucket = srcBucket + "resized"; var dstKey = "resized-" + srcKey; // Sanity check: validate that source and destination are different buckets. if (srcBucket == dstBucket) { callback("Source and destination buckets are the same."); return; } // Infer the image type. var typeMatch = srcKey.match(/\.([^.]*)$/); if (!typeMatch) { callback("Could not determine the image type."); return; } var imageType = typeMatch[1].toLowerCase(); if (imageType != "jpg" && imageType != "png") { callback(`Unsupported image type: ${imageType}`); return; } // Download the image from S3, transform, and upload to a different S3 bucket. async.waterfall([ function download(next) { // Download the image from S3 into a buffer. s3.getObject({ Bucket: srcBucket, Key: srcKey }, next); }, function transform(response, next) { gm(response.Body).size(function(err, size) { // Infer the scaling factor to avoid stretching the image unnaturally. var scalingFactor = Math.min( MAX_WIDTH / size.width, MAX_HEIGHT / size.height ); var width = scalingFactor * size.width; var height = scalingFactor * size.height; // Transform the image buffer in memory. this.resize(width, height) .toBuffer(imageType, function(err, buffer) { if (err) { next(err); } else { next(null, response.ContentType, buffer); } }); }); }, function upload(contentType, data, next) { // Stream the transformed image to a different S3 bucket. s3.putObject({ Bucket: dstBucket, Key: dstKey, Body: data, ContentType: contentType }, next); } ], function (err) { if (err) { console.error( 'Unable to resize ' + srcBucket + '/' + srcKey + ' and upload to ' + dstBucket + '/' + dstKey + ' due to an error: ' + err ); } else { console.log( 'Successfully resized ' + srcBucket + '/' + srcKey + ' and uploaded to ' + dstBucket + '/' + dstKey ); } callback(null, "message"); } ); };

O pacote de implantação é um arquivo .zip que contém o código de sua função de Lambda e as dependências.

Como criar um pacote de implantação

  1. Crie uma pasta (examplefolder) e, em seguida, crie uma subpasta (node_modules).

  2. Instale a plataforma Node.js. Para obter mais informações, consulte o website Node.js.

  3. Instale as dependências. Os exemplos de código usam as seguintes bibliotecas:

    • AWS SDK para JavaScript no Node.js

    • gm, GraphicsMagick para node.js

    • Módulo do utilitário assíncrono

    O tempo de execução do AWS Lambda já tem o AWS SDK para JavaScript no Node.js, portanto, você só precisa instalar as outras bibliotecas. Abra um prompt de comando, navegue até examplefolder e instale as bibliotecas usando o comando npm, que faz parte do Node.js.

    $ npm install async gm
  4. Salve o código de exemplo em um arquivo chamado index.js.

  5. Analise o código anterior e observe o seguinte:

    • A função conhece o nome do bucket de origem e o nome da chave do objeto dos dados do evento que recebe como parâmetros. Se o objeto for um .jpg, o código criará e salvará uma miniatura no bucket de destino.

    • O código pressupõe que o bucket de destino existe e seu nome é uma concatenação do nome do bucket de origem seguido pela string resized. Por exemplo, se o bucket de origem identificado nos dados do evento for examplebucket, o código pressuporá que você tem um bucket de destino examplebucketresized.

    • Para a miniatura que cria, o código deriva seu nome de chave como a concatenação da string resized- seguida pelo nome da chave do objeto de origem. Por exemplo, se a chave do objeto de origem for sample.jpg, o código criará um objeto em miniatura que terá a chave resized-sample.jpg.

  6. Salve o arquivo como index.js em examplefolder. Depois de concluir esta etapa, você terá a seguinte estrutura de pastas:

    index.js /node_modules/gm /node_modules/async
  7. Compacte o arquivo index.js e a pasta node_modules como CreateThumbnail.zip.

Java 11

O seguinte é um exemplo de código Java que lê eventos de entrada do Amazon S3 e cria uma miniatura. Observe que ele implementa a interface RequestHandler fornecida na biblioteca aws-lambda-java-core. Portanto, no momento em que você cria uma função do Lambda, você especifica a classe como o manipulador (isto é, example.handler). Para obter mais informações sobre o uso de interfaces para fornecer um manipulador, consulte Aproveitar interfaces predefinidas para criar handler (Java).

O tipo S3Event que o manipulador usa como tipo de entrada é uma das classes predefinidas na biblioteca aws-lambda-java-events que fornece métodos para você ler facilmente informações do evento de entrada do Amazon S3. O manipulador retorna uma string como saída.

exemplo Handler.java

package example; import java.awt.Color; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.imageio.ImageIO; import com.amazonaws.AmazonServiceException; 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.event.S3EventNotification.S3EventNotificationRecord; import com.amazonaws.services.s3.model.GetObjectRequest; import com.amazonaws.services.s3.model.ObjectMetadata; import com.amazonaws.services.s3.model.S3Object; import com.amazonaws.services.s3.AmazonS3ClientBuilder; public class Handler implements RequestHandler<S3Event, String> { private static final float MAX_WIDTH = 100; private static final float MAX_HEIGHT = 100; private final String JPG_TYPE = (String) "jpg"; private final String JPG_MIME = (String) "image/jpeg"; private final String PNG_TYPE = (String) "png"; private final String PNG_MIME = (String) "image/png"; public String handleRequest(S3Event s3event, Context context) { try { S3EventNotificationRecord record = s3event.getRecords().get(0); String srcBucket = record.getS3().getBucket().getName(); // Object key may have spaces or unicode non-ASCII characters. String srcKey = record.getS3().getObject().getUrlDecodedKey(); String dstBucket = srcBucket + "resized"; String dstKey = "resized-" + srcKey; // Sanity check: validate that source and destination are different // buckets. if (srcBucket.equals(dstBucket)) { System.out .println("Destination bucket must not match source bucket."); return ""; } // Infer the image type. Matcher matcher = Pattern.compile(".*\\.([^\\.]*)").matcher(srcKey); if (!matcher.matches()) { System.out.println("Unable to infer image type for key " + srcKey); return ""; } String imageType = matcher.group(1); if (!(JPG_TYPE.equals(imageType)) && !(PNG_TYPE.equals(imageType))) { System.out.println("Skipping non-image " + srcKey); return ""; } // Download the image from S3 into a stream AmazonS3 s3Client = AmazonS3ClientBuilder.defaultClient(); S3Object s3Object = s3Client.getObject(new GetObjectRequest( srcBucket, srcKey)); InputStream objectData = s3Object.getObjectContent(); // Read the source image BufferedImage srcImage = ImageIO.read(objectData); int srcHeight = srcImage.getHeight(); int srcWidth = srcImage.getWidth(); // Infer the scaling factor to avoid stretching the image // unnaturally float scalingFactor = Math.min(MAX_WIDTH / srcWidth, MAX_HEIGHT / srcHeight); int width = (int) (scalingFactor * srcWidth); int height = (int) (scalingFactor * srcHeight); BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g = resizedImage.createGraphics(); // Fill with white before applying semi-transparent (alpha) images g.setPaint(Color.white); g.fillRect(0, 0, width, height); // Simple bilinear resize g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g.drawImage(srcImage, 0, 0, width, height, null); g.dispose(); // Re-encode image to target format ByteArrayOutputStream os = new ByteArrayOutputStream(); ImageIO.write(resizedImage, imageType, os); InputStream is = new ByteArrayInputStream(os.toByteArray()); // Set Content-Length and Content-Type ObjectMetadata meta = new ObjectMetadata(); meta.setContentLength(os.size()); if (JPG_TYPE.equals(imageType)) { meta.setContentType(JPG_MIME); } if (PNG_TYPE.equals(imageType)) { meta.setContentType(PNG_MIME); } // Uploading to S3 destination bucket System.out.println("Writing to: " + dstBucket + "/" + dstKey); try { s3Client.putObject(dstBucket, dstKey, is, meta); } catch(AmazonServiceException e) { System.err.println(e.getErrorMessage()); System.exit(1); } System.out.println("Successfully resized " + srcBucket + "/" + srcKey + " and uploaded to " + dstBucket + "/" + dstKey); return "Ok"; } catch (IOException e) { throw new RuntimeException(e); } } }

O Amazon S3 invoca sua função do Lambda usando o tipo de invocação Event, em que o AWS Lambda executa o código de forma assíncrona. O que você retorna não importa. No entanto, neste caso, estamos implementando uma interface que requer que especifiquemos um tipo de retorno. Portanto, neste exemplo, o manipulador usa String como o tipo de retorno.

Dependências

  • aws-lambda-java-core

  • aws-lambda-java-events

  • aws-java-sdk

Crie o código com as dependências da biblioteca do Lambda para criar um pacote de implantação. Para obter instruções, consulte Pacote de implantação do AWS Lambda no Java.

Python 3

O código de amostra a seguir recebe uma entrada de evento Amazon S3 e processa a mensagem que ela contém. Ele redimensiona uma imagem no bucket de origem e salva a saída no bucket de destino.

exemplo CreateThumbnail.py

import boto3 import os import sys import uuid from urllib.parse import unquote_plus from PIL import Image import PIL.Image s3_client = boto3.client('s3') def resize_image(image_path, resized_path): with Image.open(image_path) as image: image.thumbnail(tuple(x / 2 for x in image.size)) image.save(resized_path) def handler(event, context): for record in event['Records']: bucket = record['s3']['bucket']['name'] key = unquote_plus(record['s3']['object']['key']) download_path = '/tmp/{}{}'.format(uuid.uuid4(), key) upload_path = '/tmp/resized-{}'.format(key) s3_client.download_file(bucket, key, download_path) resize_image(download_path, upload_path) s3_client.upload_file(upload_path, '{}resized'.format(bucket), key)

Como criar um pacote de implantação

  1. Copie o código de amostra em um arquivo chamado CreateThumbnail.py.

  2. Crie um ambiente virtual.

    $ virtualenv ~/shrink_venv

    $ source ~/shrink_venv/bin/activate

  3. Instale bibliotecas no ambiente virtual

    $ pip install Pillow

    $ pip install boto3

  4. Adicione o conteúdo dos pacotes de site lib e lib64 a seu arquivo .zip.

    $ cd $VIRTUAL_ENV/lib/python3.8/site-packages

    $ zip -r ~/CreateThumbnail.zip .

  5. Adicione o código python ao arquivo .zip

    $ cd ~

    $ zip -g CreateThumbnail.zip CreateThumbnail.py

Nesta página: