샘플 Amazon S3 함수 코드 - AWS Lambda

샘플 Amazon S3 함수 코드

샘플 코드는 다음 언어로 제공됩니다.

Node.js 12.x

다음은 Amazon S3 이벤트 입력을 수신하고 이벤트에 포함된 메시지를 처리하는 예제 코드입니다. 이 코드는 소스 버킷의 이미지 크기를 변경하고 출력을 대상 버킷에 저장합니다.

예 index.js

// dependencies const AWS = require('aws-sdk'); const util = require('util'); const sharp = require('sharp'); // get reference to S3 client const s3 = new AWS.S3(); exports.handler = async (event, context, callback) => { // Read options from the event parameter. console.log("Reading options from event:\n", util.inspect(event, {depth: 5})); const srcBucket = event.Records[0].s3.bucket.name; // Object key may have spaces or unicode non-ASCII characters. const srcKey = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " ")); const dstBucket = srcBucket + "-resized"; const dstKey = "resized-" + srcKey; // Infer the image type from the file suffix. const typeMatch = srcKey.match(/\.([^.]*)$/); if (!typeMatch) { console.log("Could not determine the image type."); return; } // Check that the image type is supported const imageType = typeMatch[1].toLowerCase(); if (imageType != "jpg" && imageType != "png") { console.log(`Unsupported image type: ${imageType}`); return; } // Download the image from the S3 source bucket. try { const params = { Bucket: srcBucket, Key: srcKey }; var origimage = await s3.getObject(params).promise(); } catch (error) { console.log(error); return; } // set thumbnail width. Resize will set the height automatically to maintain aspect ratio. const width = 200; // Use the Sharp module to resize the image and save in a buffer. try { var buffer = await sharp(origimage.Body).resize(width).toBuffer(); } catch (error) { console.log(error); return; } // Upload the thumbnail image to the destination bucket try { const destparams = { Bucket: dstBucket, Key: dstKey, Body: buffer, ContentType: "image" }; const putResult = await s3.putObject(destparams).promise(); } catch (error) { console.log(error); return; } console.log('Successfully resized ' + srcBucket + '/' + srcKey + ' and uploaded to ' + dstBucket + '/' + dstKey); };

배포 패키지는 Lambda 함수 코드 및 종속성이 포함되어 있는 .zip 파일입니다.

배포 패키지를 만들려면

  1. 폴더(examplefolder)를 생성한 다음 하위 폴더(node_modules)를 생성합니다.

  2. 종속 항목을 설치합니다. 이 코드 예제는 다음 라이브러리를 사용합니다.

    • Node.js로 작성된 JavaScript용 AWS SDK

    • node.js에 대한 샤프

    AWS Lambda 런타임에는 Node.js에 이미 JavaScript용 AWS SDK가 있으므로 Sharp 라이브러리만 설치하면 됩니다. 명령 프롬프트를 열고 examplefolder로 이동한 후 Node.js의 일부인 npm 명령을 사용하여 라이브러리를 설치합니다. Linux의 경우 다음 명령을 사용합니다.

    $ npm install sharp

    macOS의 경우 다음 명령을 사용합니다.

    $ npm install --arch=x64 --platform=linux --target=12.13.0 sharp
  3. 샘플 코드를 index.js 파일에 저장합니다.

  4. 앞의 코드를 검토하고 다음 사항을 확인합니다.

    • 이 함수는 파라미터로 받은 이벤트 데이터에서 원본 버킷 이름과 객체 키 이름을 알고 있습니다. 객체가 .jpg인 경우, 코드는 썸네일을 만들고 대상 버킷에 저장합니다.

    • 이 코드는 대상 버킷이 존재하고 해당 이름이 원본 버킷 이름과 -resized 문자열이 이어진 것이라고 가정합니다. 예를 들어 이벤트 데이터에서 식별된 원본 버킷이 examplebucket인 경우 코드는 사용자에게 examplebucket-resized 대상 버킷이 있다고 가정합니다.

    • 생성하는 썸네일의 경우 코드는 resized- 문자열과 소스 객체 키 이름이 연결된 키 이름을 가져옵니다. 예를 들어 소스 객체 키가 sample.jpg인 경우 코드는 키가 resized-sample.jpg인 썸네일 객체를 만듭니다.

  5. 파일을 index.jsexamplefolder로 저장합니다. 이 단계를 완료한 후에는 다음과 같은 폴더 구조를 갖게 됩니다.

    index.js /node_modules/sharp
  6. index.js 파일과 node_modules 폴더를 CreateThumbnail.zip으로 압축합니다.

Java 11

다음은 수신하는 Amazon S3 이벤트를 읽고 썸네일을 생성하는 Java 코드의 예입니다. 이는 aws-lambda-java-core 라이브러리에 제공된 RequestHandler 인터페이스를 구현합니다. 따라서 Lambda 함수를 만들 때 클래스를 핸들러(즉, example.handler)로 지정합니다. 인터페이스를 사용하여 핸들러를 제공하는 방법에 대한 자세한 내용은 핸들러 인터페이스 단원을 참조하십시오.

핸들러가 입력 유형으로 사용하는 S3Event 유형은 수신하는 Amazon S3 이벤트에서 정보를 쉽게 읽을 수 있는 방법을 제공하는 aws-lambda-java-events 라이브러리의 사전 정의된 클래스 중 하나입니다. 핸들러는 문자열을 출력으로 반환합니다.

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

Amazon S3는 Event 호출 유형을 사용해 Lambda 함수를 호출하며, 여기에서 AWS Lambda는 코드를 비동기식으로 실행합니다. 반환하는 항목은 중요하지 않습니다. 하지만 이 경우 반환 유형을 지정해야 하는 인터페이스를 구현하므로 이 예제에서는 핸들러가 String을 반환 유형으로 사용합니다.

종속성

  • aws-lambda-java-core

  • aws-lambda-java-events

  • aws-java-sdk

Lambda 라이브러리 종속성으로 코드를 빌드하여 배포 패키지를 만듭니다. 지침은 AWS Lambda 배포 패키지(Java) 단원을 참조하십시오.

Python 3

다음은 Amazon S3 이벤트 입력을 수신하고 이벤트에 포함된 메시지를 처리하는 예제 코드입니다. 이 코드는 소스 버킷의 이미지 크기를 변경하고 출력을 대상 버킷에 저장합니다.

예 lambda_function.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 lambda_handler(event, context): for record in event['Records']: bucket = record['s3']['bucket']['name'] key = unquote_plus(record['s3']['object']['key']) tmpkey = key.replace('/', '') download_path = '/tmp/{}{}'.format(uuid.uuid4(), tmpkey) upload_path = '/tmp/resized-{}'.format(tmpkey) s3_client.download_file(bucket, key, download_path) resize_image(download_path, upload_path) s3_client.upload_file(upload_path, '{}-resized'.format(bucket), key)
참고

작업 배포 패키지를 생성하려면 이 코드에서 사용하는 이미지 라이브러리를 Linux 환경에 설치해야 합니다.

배포 패키지를 만들려면

  1. 샘플 코드를 lambda_function.py이라는 파일에 복사합니다.

  2. 가상 환경을 생성합니다.

    s3-python$ virtualenv v-env s3-python$ source v-env/bin/activate
  3. 가상 환경에 라이브러리를 설치합니다.

    (v-env) s3-python$ pip install Pillow boto3
  4. 설치된 라이브러리의 내용이 포함된 배포 패키지를 생성합니다.

    (v-env) s3-python$ cd $VIRTUAL_ENV/lib/python3.8/site-packages (v-env) python-s3/v-env/lib/python3.8/site-packages$ zip -r9 ${OLDPWD}/function.zip .
  5. 배포 패키지에 핸들러 코드를 추가하고 가상 환경을 비활성화합니다.

    (v-env) python-s3/v-env/lib/python3.8/site-packages$ cd ${OLDPWD} (v-env) python-s3$ zip -g function.zip lambda_function.py adding: lambda_function.py (deflated 55%) (v-env) python-s3$ deactivate