AWS Lambda學習2:通過S3事件觸發調用Lambda函數,實現縮略圖地生成

創建一個Amazon Lambda函數,實現從S3源存儲桶讀取圖片對象並創建縮略圖到目標存儲桶,開發實現過程如下:

1、創建存儲桶並上傳示例對象

(1)打開 Amazon S3 控制檯

(2)創建兩個存儲桶。源存儲桶lambda-demo1-bucket,目標存儲桶lambda-demo1-bucketresized。

(3)在源存儲桶中,上傳一個 .jpg 對象 sidatianwang.jpg。

2、創建Lambda函數

(1)創建Maven項目,pom.xml中添加如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
       <modelVersion>4.0.0</modelVersion>
       <groupId>com.lenovo</groupId>
       <artifactId>lambda</artifactId>
       <version>0.0.1-SNAPSHOT</version>
       <packaging>jar</packaging>
       <name>lambda</name>
       <url>http://maven.apache.org</url>
       <properties>
              <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
       </properties>
 
       <dependencies>
              <dependency>
                     <groupId>junit</groupId>
                     <artifactId>junit</artifactId>
                     <version>3.8.1</version>
                     <scope>test</scope>
              </dependency>
              <dependency>
                     <groupId>net.lingala.zip4j</groupId>
                     <artifactId>zip4j</artifactId>
                     <version>1.3.2</version>
              </dependency>
              <dependency>
                     <groupId>com.amazonaws</groupId>
                     <artifactId>aws-lambda-java-core</artifactId>
                     <version>1.2.0</version>
              </dependency>
              <dependency>
                     <groupId>com.amazonaws</groupId>
                     <artifactId>aws-lambda-java-events</artifactId>
                     <version>2.2.2</version>
              </dependency>
              <dependency>
                     <groupId>com.amazonaws</groupId>
                     <artifactId>aws-java-sdk-core</artifactId>
                     <version>1.11.520</version>
              </dependency>
              <dependency>
                     <groupId>com.amazonaws</groupId>
                     <artifactId>aws-java-sdk-s3</artifactId>
                     <version>1.11.520</version>
              </dependency>
              <dependency>
                     <groupId>com.amazonaws</groupId>
                     <artifactId>aws-java-sdk-lambda</artifactId>
                     <version>1.11.520</version>
              </dependency>
              <dependency>
                     <groupId>com.amazonaws</groupId>
                     <artifactId>aws-java-sdk-codebuild</artifactId>
                     <version>1.11.745</version>
              </dependency>
              <!-- <dependency>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-shade-plugin</artifactId>
                     <version>3.2.1</version>
              </dependency> -->
       </dependencies>
 
       <build>
              <plugins>
                     <plugin>
                            <groupId>org.apache.maven.plugins</groupId>
                            <artifactId>maven-shade-plugin</artifactId>
                            <version>2.3</version>
                            <configuration>                                     <createDependencyReducedPom>false</createDependencyReducedPom>
                            </configuration>
                            <executions>
                                  <execution>
                                          <phase>package</phase>
                                          <goals>
                                                 <goal>shade</goal>
                                          </goals>
                                   </execution>
                            </executions>
                     </plugin>
              </plugins>
       </build>
</project>

(2)編寫主函數,接收Amazon S3事件輸入並對其包含的消息進行處理。

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

(3)將maven工程打成jar包(以eclipse爲例說明)

a. 清理,工程點擊右鍵 → run as → Maven clean

b. 打包,工程點擊右鍵 → run as → Maven install

在target目錄下獲取生成的jar包lambda-0.0.1-SNAPSHOT.jar

(4)登錄Amazon lambda服務控制檯,創建lambda測試函數

a. 名稱隨意;

b. 選擇語言;

c. 選擇或創建角色,角色要有lambda執行權限。

d. 上傳jar包lambda-0.0.1-SNAPSHOT.jar

  注意處理程序命名規則:包.::方法名(例如:example.Handler::handleRequest

e. 添加S3觸發器,通過S3事件觸發調用lambda函數

f. 點擊保存,保存lambda函數

3、配置S3事件通知

(1)打開 Amazon S3 控制檯,依次執行:選擇源存儲桶→選擇屬性→高級選項卡下選擇事件→添加通知

(2)在 Events (事件) 下,使用以下設置配置通知。

         名稱 – lambda-trigger;

         事件 – ObjectCreate (All);

         發送到 – Lambda function;

         Lambda – test10。

4、點擊測試,編寫測試用例。

(1)點擊配置測試事件,填寫測試用例。(json格式,對應方法的參數)

{
  "Records": [
    {
      "eventVersion": "2.0",
      "eventSource": "aws:s3",
      "awsRegion": "ap-southeast-1",
      "eventTime": "1970-01-01T00:00:00.000Z",
      "eventName": "ObjectCreated:Put",
      "userIdentity": {
        "principalId": "EXAMPLE"
      },
      "requestParameters": {
        "sourceIPAddress": "127.0.0.1"
      },
      "responseElements": {
        "x-amz-request-id": "EXAMPLE123456789",
        "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
      },
      "s3": {
        "s3SchemaVersion": "1.0",
        "configurationId": "testConfigRule",
        "bucket": {
          "name": "lambda-demo1-bucket",
          "ownerIdentity": {
            "principalId": "*"
          },
          "arn": "arn:aws:s3:::lambda-demo1-bucket"
        },
        "object": {
          "key": "sidatianwang.jpg",
          "size": 1024,
          "eTag": "0123456789abcdef0123456789abcdef",
          "sequencer": "0A1B2C3D4E5F678901"
        }
      }
    }
  ]
}

(2)點擊測試按鈕,即可運行

(3)返回Amazon S3控制檯,驗證目標存儲桶中是否生成縮略圖

經過驗證發現,將圖片sidatianwang.jpg上傳到S3源存儲桶lambda-demo1-bucket後,通過S3事件觸發lambda函數test10,在S3目標存儲桶lambda-demo1-bucketresized中生成了縮略圖resized-sidatianwang.jpg。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章