やりたいこと
S3においた画像イメージをLambda経由で取得しkotlinで表示する。
問題
元々はS3に格納した画像をLambdaで呼び出し、ByteArray形式に変換してクライアント端末に渡していたのですが、Lambdaにはレスポンス6MBの制限があり、大量の画像データを扱えなくなりました。
解決方法
S3のPre-Signed URLを使います。
Pre-Sined URLを使うと、S3オブジェクトへの限定的なアクセスを提供することが可能で、URLを渡すため、ByteArrayを渡すより格段に容量を減らせます。
実装例
S3
TESTバケットにsample.jpgを格納
Lambda
-
環境:AWS Lambda Python 3.9
-
アタッチするポリシー:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject"
],
"Resource": "arn:aws:s3:::sample-s3-presignedurl/*"
}
]
}
- Lambda関数
# -- coding: utf-8 --
import json
import json
import boto3
import base64
from boto3.dynamodb.conditions import Key #Keyオブジェクトを利用できるようにする
S3_BUCKET_NAME = 'TEST'
S3_OBJECT_KEY = 'sample.jpg'
s3 = boto3.client('s3')
def lambda_handler(event, context):
# TODO implement
url = s3.generate_presigned_url(
'get_object',
Params={
'Bucket': S3_BUCKET_NAME,
'Key': S3_OBJECT_KEY
},
ExpiresIn=3600
)
return {
'statusCode': 200,
'body': url
}
kotlin
- 本題ではないので、API Gatewayやcoroutine使ってhttps通信するとことろは省きます。
- 頑張ってLambdaの戻り値を取得した前提です
- GlideというURL画像を取得するライブラリを使います。
Glideの初期設定
「build.gradle」のdependenciesに下記のコードを追加します
implementation 'com.github.bumptech.glide:glide:4.10.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.10.0'
レイアウトの作成
ImageViewを作成
activity_glide.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".GlideActivity"
android:gravity="center">
<ImageView
android:layout_width="match_parent"
android:layout_height="300dp"
android:id="@+id/glideTest"
android:layout_weight="1" />
</LinearLayout>
Glideで画像をロード
GlideUrl を継承したクラスを用意し、getCacheKeyメソッドをオーバーライドします
GlideActivity.kt
import com.bumptech.glide.load.model.GlideUrl
class GlideNoTokenUrl(private val url: String) : GlideUrl(url) {
override fun getCacheKey(): String {
// Domain(バケット名含む) + Path で判定する
return url.substringBefore("?")
}
}
Activity内でGlideで画像をロードしてImageViewに格納します
GlideActivity.kt
package com.example.hoge
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.ImageView
import com.bumptech.glide.Glide
class GlideActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_glide)
val glideTest = findViewById<ImageView>(R.id.glideTest) //イメージビュー
// API Gateway+Lambdaで画像のPre-Signed URLを取得
imageURL = getImageURL() // ここでHTTP通信などして画像URLを取得してください
//GlideでImageViewに設定
Glide.with(context)
.load(GlideNoTokenUrl(url)) // ロードしたいイメージのURLを入力
.placeholder(R.drawable.dreamhanks) //イメージをロード中に見せるイメージ設定
.into(glideTest) // セットしたいImageViewを入力
}
}
}
Glideの主要メソッド
- 「with」:ContextやActivityについて設定
- 「load」:実際にロードしたいイメージのURLを設定
- 「placeholder」:イメージをロード中に見せるイメージを設定(なくてもいい)
- 「into」:イメージを適用する「ImageView」を設定
以上
参考にさせていただいた素晴らしいサイト様
- 21. 【Android/Kotlin】Glide(イメージをロード)
- S3-Pre-Signed-URLでダウンロードした画像を Android の画像ライブラリ Glide 4 でキャッシュする
- Lambdaで6MBを超えるデータをReturnできなかったので、S3のPre-Signed URLを使った話
- S3に直接アップロード可能なPre-Signed URLをLambdaで作ってみる
旅行アプリ、Tig Travelをリリースしました
おすすめの旅行プランを多数掲載。旅行プランをカスタマイズし、自分だけのプランを簡単に作成できます!