Skip to content

Commit 79a9f41

Browse files
committed
add resize impl
1 parent 2d3bc55 commit 79a9f41

File tree

4 files changed

+174
-8
lines changed

4 files changed

+174
-8
lines changed

README.md

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# image-resizer-lambda-serverless
2+
AWS Lambda to resize image when upload image to specific S3 bucket.
3+
4+
## Runtime
5+
- Ruby2.7
6+
7+
## Deploy & Resource Setting
8+
- Serverless Framework
9+
10+
## Setup
11+
12+
#### required
13+
- Docker
14+
- AWS Account & AWS CLI
15+
16+
### Add AWS credential
17+
18+
```bash
19+
$ touch docker.env
20+
```
21+
22+
`docker.env`
23+
24+
```bash
25+
AWS_ACCESS_KEY_ID=xxx
26+
AWS_DEFAULT_REGION=ap-northeast-1
27+
AWS_SECRET_ACCESS_KEY=xxx
28+
```
29+
30+
### docker-compose
31+
32+
```bash
33+
$ docker-compose build
34+
$ docker-compose --rm run serverless sh
35+
36+
sh-4.2# bundle config set path 'vendor/bundle'
37+
sh-4.2# bundle install
38+
```
39+
40+
## Debug Lambda
41+
42+
### use `bundle exec ruby` in docker-compose
43+
For example, you insert `binding.irb` in `handler.rb` for debug.
44+
45+
You command below
46+
47+
```bash
48+
sh-4.2# bundle exec ruby handler.rb
49+
```
50+
51+
### docker-lambda
52+
- WIP
53+
54+
## Deploy
55+
56+
```bash
57+
sh-4.2# sls deploy
58+
59+
# Remove Resources
60+
sh-4.2# sls remove
61+
```
62+
63+
## Lambda Layer
64+
deploy [`libvips`](https://github.com/libvips/libvips) to lambda layer for native extendions.
65+
66+
use https://github.com/customink/ruby-vips-lambda
67+
68+
```
69+
$ git clone https://github.com/customink/ruby-vips-lambda.git
70+
$ cd ruby-vips-lambda
71+
$ ./bin/deploy
72+
```
73+
74+
#### If you deploy to layer other region(not us-east-1)
75+
- change `AWS_DEFAULT_REGION` in `ruby-vips-lambda/bin/deploy`
76+
77+
```
78+
#!/bin/bash
79+
80+
set -e
81+
82+
./bin/build
83+
84+
export VIPS_VERSION=$(cat share/VIPS_VERSION)
85+
export LAYER_NAME="rubyvips${VIPS_VERSION//./}-27"
86+
87+
# change here
88+
export AWS_REGION=${AWS_REGION:=ap-northeast-1}
89+
90+
aws lambda publish-layer-version \
91+
--region $AWS_REGION \
92+
--layer-name $LAYER_NAME \
93+
--description "Libvips for Ruby FFI." \
94+
--zip-file "fileb://share/libvips.zip"
95+
```

handler.rb

+5-8
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
require 'json'
1+
require_relative "./lib/image_service"
22

33
def handler(event:, context:)
4-
{
5-
statusCode: 200,
6-
body: {
7-
message: 'Go Serverless v1.0! Your function executed successfully!',
8-
input: event
9-
}.to_json
10-
}
4+
key = event["Records"][0].dig("s3", "object", "key")
5+
resizer = ImageService::Resizer.new(key, 280)
6+
7+
resizer.resize!
118
end

lib/image_service.rb

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
require_relative "./image_service/resizer"
2+
3+
module ImageService
4+
def self.❨╯°□°❩╯︵┻━┻
5+
puts "Calm down, yo."
6+
end
7+
end

lib/image_service/resizer.rb

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
require "aws-sdk-s3"
2+
require "image_processing/vips"
3+
4+
module ImageService
5+
class Resizer
6+
CLIENT = Aws::S3::Client.new(region: "ap-northeast-1")
7+
BUCKET = "yuichi-kojima-test2"
8+
9+
attr_reader :key, :size
10+
11+
def initialize(key, width = 280, height = nil)
12+
@key = key
13+
@width = width
14+
@height = height
15+
end
16+
17+
def resize!
18+
return if resized?
19+
20+
resized = ImageProcessing::Vips
21+
.source(source)
22+
.resize_to_limit(@width, @height)
23+
.call(save: false)
24+
.write_to_buffer(File.extname(@key))
25+
26+
put_object resized, new_key
27+
end
28+
29+
def source
30+
if File.extname(@key) == ".png"
31+
Vips::Image.pngload_buffer(get_object)
32+
elsif File.extname(@key) == ".gif"
33+
Vips::Image.thumbnail(@key, @width)
34+
else
35+
Vips::Image.new_from_buffer(get_object, File.extname(@key))
36+
end
37+
end
38+
39+
def new_key
40+
"resized/#{File.basename(@key, File.extname(@key))}-#{@width}#{File.extname(@key)}"
41+
end
42+
43+
def get_object
44+
CLIENT.get_object(bucket: BUCKET, key: @key).body.read
45+
end
46+
47+
def put_object(object, put_key)
48+
CLIENT.put_object(
49+
bucket: BUCKET,
50+
key: put_key,
51+
body: object,
52+
metadata: { resized: "1" }
53+
)
54+
end
55+
56+
def resized?
57+
metadata[:resized]
58+
end
59+
60+
def metadata
61+
response = CLIENT.head_object(bucket: BUCKET, key: @key)
62+
response.metadata || {}
63+
rescue Aws::S3::Errors::NotFound
64+
{}
65+
end
66+
end
67+
end

0 commit comments

Comments
 (0)