Uso di Lambda per oggetti Amazon S3 per aggiungere dinamicamente una filigrana alle immagini man mano che vengono recuperate
TUTORIAL
Panoramica
Con Lambda per oggetti Amazon S3 puoi aggiungere il tuo codice alle richieste GET, HEAD e LIST S3 per modificare i dati quando vengono restituiti a un'applicazione. Puoi utilizzare il codice personalizzato per modificare i dati restituiti dalle richieste GET S3 per convertire i formati dei dati (ad esempio, da XML a JSON), ridimensionare le immagini in modo dinamico, revisionare i dati confidenziali e molto altro. Puoi utilizzare Lambda per oggetti S3 per modificare l'output delle richieste LIST S3 per creare una visualizzazione personalizzata dell'oggetto in un bucket e delle richieste HEAD S3, per modificare i metadati dell'oggetto, come il nome e le dimensioni dell'oggetto.
Lo scopo di questo tutorial è mostrarti come iniziare a usare Lambda per oggetti Amazon S3. Molte organizzazioni archiviano immagini in Amazon S3 a cui accedono applicazioni diverse, ognuna con requisiti di formato dati unici. In alcuni casi, potrebbe essere necessario modificare le immagini in modo da includere una filigrana a seconda dell'utente che accede all'immagine (ad esempio, un abbonato pagante può visualizzare le immagini senza filigrana, mentre un utente non pagante riceve un'immagine con filigrana).
In questo tutorial, useremo Lambda per oggetti S3 per aggiungere una filigrana a un'immagine mentre viene recuperata da Amazon S3. Lambda per oggetti S3 può essere utilizzato per modificare i dati mentre vengono recuperati da Amazon S3 senza modificare l'oggetto esistente o mantenere più copie derivate dei dati. Presentando più visualizzazioni degli stessi dati ed eliminando la necessità di archiviare copie derivate, è possibile risparmiare sui costi di archiviazione.
Obiettivi
In questo tutorial, imparerai a:
- Creare un bucket Amazon S3
- Creare un punto di accesso S3
- Creare una funzione AWS Lambda per modificare le immagini
- Creare un punto di accesso Lambda per oggetti S3
Prerequisiti
Per completare questo tutorial devi disporre di un account AWS. Accedi a questa pagina di supporto per ulteriori informazioni su come creare e attivare un nuovo account AWS.
Puoi creare un utente IAM per il tutorial oppure aggiungere autorizzazioni a un utente IAM esistente. Per completare questo tutorial, il tuo utente IAM deve includere le seguenti autorizzazioni per accedere alle risorse AWS pertinenti ed eseguire operazioni specifiche:
- s3:CreateBucket
- s3:PutObject
- s3:GetObject
- s3:ListBucket
- s3:CreateAccessPoint
- s3:CreateAccessPointForObjectLambda
- s3-object-lambda:WriteGetObjectResponse
- lambda:CreateFunction
- lambda:InvokeFunction
- iam:AttachRolePolicy
- iam:CreateRole
- iam:PutRolePolicy
Per eliminare le risorse create in questo tutorial, saranno necessarie le seguenti autorizzazioni IAM:
- s3:DeleteBucket
- s3:DeleteAccessPoint
- s3:DeleteAccessPointForObjectLambda
- lambda:DeleteFunction
- iam:DeleteRole
Esperienza AWS
Tempo per il completamento
20 minuti
Costo richiesto per il completamento
Meno di 1 USD (pagina dei prezzi di Amazon S3)
Requisiti
Account AWS*
*Gli account creati nelle ultime 24 ore potrebbero non avere ancora accesso a tutte le risorse richieste per questo tutorial.
Servizi utilizzati
Ultimo aggiornamento
1 febbraio 2023
Prerequisiti
Per completare questo tutorial devi disporre di un account AWS. Accedi a questa pagina di supporto per ulteriori informazioni su come creare e attivare un nuovo account AWS.
Puoi creare un utente IAM per il tutorial oppure aggiungere autorizzazioni a un utente IAM esistente. Per completare questo tutorial, il tuo utente IAM deve includere le seguenti autorizzazioni per accedere alle risorse AWS pertinenti ed eseguire operazioni specifiche:
-
Autorizzazioni richieste
- s3:CreateBucket
- s3:PutObject
- s3:GetObject
- s3:ListBucket
- s3:CreateAccessPoint
- s3:CreateAccessPointForObjectLambda
- s3-object-lambda:WriteGetObjectResponse
- lambda:CreateFunction
- lambda:InvokeFunction
- iam:AttachRolePolicy
- iam:CreateRole
- iam:PutRolePolicy
-
Autorizzazioni richieste
Per eliminare le risorse create in questo tutorial, saranno necessarie le seguenti autorizzazioni IAM:
- s3:DeleteBucket
- s3:DeleteAccessPoint
- s3:DeleteAccessPointForObjectLambda
- lambda:DeleteFunction
- iam:DeleteRole
Implementazione
Fase 1: Creazione di un bucket Amazon S3
1.1 - Accesso alla console Amazon S3
- Accedi alla Console di gestione AWS e apri la console di Amazon S3.
1.2 - Creazione di un bucket S3
- Seleziona Bucket dal menu Amazon S3 nel pannello di navigazione sulla sinistra, quindi scegli il pulsante Crea bucket.
1.3
- Nel campo Nome bucket, inserisci un nome descrittivo univoco a livello globale per il bucket. Seleziona la Regione AWS in cui desideri creare il bucket. Più avanti in questo tutorial creeremo un'altra risorsa che dovrà trovarsi nella stessa Regione AWS.
- Le opzioni rimanenti possono restare con le selezioni predefinite. Scorri fino in fondo alla pagina e seleziona Crea bucket.
Fase 2: Caricamento di un oggetto
2.1 - Caricamento di un oggetto
- Dall'elenco di bucket disponibili, seleziona il nome del bucket appena creato.
2.2
- Quindi, assicurati che la scheda Oggetti sia selezionata. Quindi, dalla sezione Oggetti, scegli Carica.
2.3 - Aggiunta di file
- Scegli il pulsante Aggiungi file e seleziona il file che desideri caricare dal tuo browser di file.
- Se lo desideri, puoi caricare questa immagine di esempio.
2.4 - Caricamento
- Scorri fino in fondo alla pagina e scegli il pulsante Carica.
2.5
- Una volta completato il caricamento, seleziona il pulsante Chiudi.
Fase 3: Creazione di un punto di accesso S3
Crea un punto di accesso Amazon S3 che verrà utilizzato per supportare il punto di accesso Lambda per oggetti S3, che verrà creato più avanti nel tutorial.
3.1 - Creazione di un punto di accesso S3
- Vai alla console S3 e seleziona l'opzione del menu Punti di accesso nel pannello di navigazione sulla sinistra. Quindi, scegli il pulsante Crea punto di accesso.
3.2
- Nella sezione Proprietà, inserisci il nome del punto di accesso desiderato e scegli il nome del bucket inserito nel passaggio 1 selezionando il pulsante Sfoglia S3. Quindi, imposta il campo Origine della rete su Internet.
3.3
- Mantieni tutte le altre impostazioni predefinite così come sono. Scorri fino alla fine della pagina e scegli il pulsante Crea punto di accesso.
3.4
- Quando si accede a Punti di accesso nel riquadro di navigazione sulla sinistra, il punto di accesso S3 sarà visualizzato nell'elenco.
Fase 4: Creazione della funzione Lambda
- Quindi, crea una funzione Lambda che verrà richiamata quando le richieste GET S3 vengono effettuate tramite un punto di accesso di Lambda per oggetti S3.
- Per creare e testare Lambda per oggetti S3 utilizzeremo AWS CloudShell dalla Console di gestione AWS. Per creare la soluzione, puoi usare il tuo computer o un'istanza AWS Cloud9 per creare la soluzione se sono soddisfatti i seguenti requisiti:
- Versione più recente dell'interfaccia a riga di comando (CLI) di AWS
- Credenziali per creare funzioni/livelli AWS Lambda e ruolo IAM
- Python 3.9
- utilità zip
- utilità jq
4.1 - Avvio di un terminale CloudShell
Seleziona l'icona CloudShell nel menu in alto a destra nella Console di gestione AWS.
Se viene visualizzata una finestra introduttiva di CloudShell, puoi leggere il contenuto e scegliere Chiudi.
Si aprirà una nuova scheda del browser con il terminale CloudShell (simile alla seguente schermata):
4.2 - Preparazione di CloudShell per implementare la funzione Lambda
- Esegui il codice riportato in CloudShell per preparare l'ambiente e distribuire il livello Lambda con il modulo Pillow. Copia e incolla il seguente codice in CloudShell per installare le dipendenze richieste e implementare la funzione Lambda.
# Install the required libraries to build new python
sudo yum install gcc openssl-devel bzip2-devel libffi-devel -y
# Install Pyenv
curl https://pyenv.run | bash
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
source ~/.bash_profile
# Install Python version 3.9
pyenv install 3.9.13
pyenv global 3.9.13
# Build the pillow Lambda layer
mkdir python
cd python
pip install pillow -t .
cd ..
zip -r9 pillow.zip python/
aws lambda publish-layer-version \
--layer-name Pillow \
--description "Python Image Library" \
--license-info "HPND" \
--zip-file fileb://pillow.zip \
--compatible-runtimes python3.9
Nota: quando si copia e incolla il codice, CloudShell apre una finestra di avviso per confermare che si sta per incollare il codice su più righe. Seleziona Incolla.
Il completamento di questo passaggio può richiedere 10-15 minuti.
4.3 - Creazione della funzione Lambda
- Scarica un font TrueType che verrà utilizzato dalla funzione Lambda per aggiungere una filigrana a un'immagine. Copia e incolla i seguenti comandi in CloudShell.
wget https://m.media-amazon.com/images/G/01/mobile-apps/dex/alexa/branding/Amazon_Typefaces_Complete_Font_Set_Mar2020.zip
- Estrai il carattere TrueType che verrà utilizzato per scrivere il testo con filigrana nell'immagine.
unzip -oj Amazon_Typefaces_Complete_Font_Set_Mar2020.zip "Amazon_Typefaces_Complete_Font_Set_Mar2020/Ember/AmazonEmber_Rg.ttf"
- Crea il codice Lambda che verrà utilizzato per elaborare le richieste Lambda per oggetti S3.
cat << EOF > lambda.py
import boto3
import json
import os
import logging
from io import BytesIO
from PIL import Image, ImageDraw, ImageFont
from urllib import request
from urllib.parse import urlparse, parse_qs, unquote
from urllib.error import HTTPError
from typing import Optional
logger = logging.getLogger('S3-img-processing')
logger.addHandler(logging.StreamHandler())
logger.setLevel(getattr(logging, os.getenv('LOG_LEVEL', 'INFO')))
FILE_EXT = {
'JPEG': ['.jpg', '.jpeg'],
'PNG': ['.png'],
'TIFF': ['.tif']
}
OPACITY = 64 # 0 = transparent and 255 = full solid
def get_img_encoding(file_ext: str) -> Optional[str]:
result = None
for key, value in FILE_EXT.items():
if file_ext in value:
result = key
break
return result
def add_watermark(img: Image, text: str) -> Image:
font = ImageFont.truetype("AmazonEmber_Rg.ttf", 82)
txt = Image.new('RGBA', img.size, (255, 255, 255, 0))
if img.mode != 'RGBA':
image = img.convert('RGBA')
else:
image = img
d = ImageDraw.Draw(txt)
# Positioning Text
width, height = image.size
text_width, text_height = d.textsize(text, font)
x = width / 2 - text_width / 2
y = height / 2 - text_height / 2
# Applying Text
d.text((x, y), text, fill=(255, 255, 255, OPACITY), font=font)
# Combining Original Image with Text and Saving
watermarked = Image.alpha_composite(image, txt)
return watermarked
def handler(event, context) -> dict:
logger.debug(json.dumps(event))
object_context = event["getObjectContext"]
# Get the presigned URL to fetch the requested original object
# from S3
s3_url = object_context["inputS3Url"]
# Extract the route and request token from the input context
request_route = object_context["outputRoute"]
request_token = object_context["outputToken"]
parsed_url = urlparse(event['userRequest']['url'])
object_key = parsed_url.path
logger.info(f'Object to retrieve: {object_key}')
parsed_qs = parse_qs(parsed_url.query)
for k, v in parsed_qs.items():
parsed_qs[k][0] = unquote(v[0])
filename = os.path.splitext(os.path.basename(object_key))
# Get the original S3 object using the presigned URL
req = request.Request(s3_url)
try:
response = request.urlopen(req)
except HTTPError as e:
logger.info(f'Error downloading the object. Error code: {e.code}')
logger.exception(e.read())
return {'status_code': e.code}
if encoding := get_img_encoding(filename[1].lower()):
logger.info(f'Compatible Image format found! Processing image: {"".join(filename)}')
img = Image.open(response)
logger.debug(f'Image format: {img.format}')
logger.debug(f'Image mode: {img.mode}')
logger.debug(f'Image Width: {img.width}')
logger.debug(f'Image Height: {img.height}')
img_result = add_watermark(img, parsed_qs.get('X-Amz-watermark', ['Watermark'])[0])
img_bytes = BytesIO()
if img.mode != 'RGBA':
# Watermark added an Alpha channel that is not compatible with JPEG. We need to convert to RGB to save
img_result = img_result.convert('RGB')
img_result.save(img_bytes, format='JPEG')
else:
# Will use the original image format (PNG, GIF, TIFF, etc.)
img_result.save(img_bytes, encoding)
img_bytes.seek(0)
transformed_object = img_bytes.read()
else:
logger.info(f'File format not compatible. Bypass file: {"".join(filename)}')
transformed_object = response.read()
# Write object back to S3 Object Lambda
s3 = boto3.client('s3')
# The WriteGetObjectResponse API sends the transformed data
if os.getenv('AWS_EXECUTION_ENV'):
s3.write_get_object_response(
Body=transformed_object,
RequestRoute=request_route,
RequestToken=request_token)
else:
# Running in a local environment. Saving the file locally
with open(f'myImage{filename[1]}', 'wb') as f:
logger.debug(f'Writing file: myImage{filename[1]} to the local filesystem')
f.write(transformed_object)
# Exit the Lambda function: return the status code
return {'status_code': 200}
EOF
- Crea il file zip Lambda che contiene il codice Python e il file del font TrueType.
zip -r9 lambda.zip lambda.py AmazonEmber_Rg.ttf
- Crea il ruolo IAM da collegare alla funzione Lambda.
aws iam create-role --role-name ol-lambda-images --assume-role-policy-document '{"Version": "2012-10-17","Statement": [{"Effect": "Allow", "Principal": {"Service": "lambda.amazonaws.com"}, "Action": "sts:AssumeRole"}]}'
- Allega una policy IAM predefinita al ruolo IAM creato in precedenza. Questa policy contiene le autorizzazioni minime necessarie per eseguire la funzione Lambda.
aws iam attach-role-policy --role-name ol-lambda-images --policy-arn arn:aws:iam::aws:policy/service-role/AmazonS3ObjectLambdaExecutionRolePolicy
export OL_LAMBDA_ROLE=$(aws iam get-role --role-name ol-lambda-images | jq -r .Role.Arn)
export LAMBDA_LAYER=$(aws lambda list-layers --query 'Layers[?contains(LayerName, `Pillow`) == `true`].LatestMatchingVersion.LayerVersionArn' | jq -r .[])
- Crea e carica la funzione Lambda.
aws lambda create-function --function-name ol_image_processing \
--zip-file fileb://lambda.zip --handler lambda.handler --runtime python3.9 \
--role $OL_LAMBDA_ROLE \
--layers $LAMBDA_LAYER \
--memory-size 1024
Fase 5: Creazione di un punto di accesso di Lambda per oggetti S3
5.1 - Creazione del punto di accesso di Lambda per oggetti S3
- Accedi alla console S3 e scegli Punti di accesso Lambda dell'oggetto nel pannello di navigazione sulla sinistra. Scegli il pulsante Crea punto di accesso Lambda dell'oggetto.
Nella sezione Generale, per il nome del punto di accesso Lambda dell'oggetto, inserisci ol-amazon-s3-images-guide.
Assicurati che la Regione AWS per il punto di accesso Lambda per oggetti S3 corrisponda alla Regione AWS specificata durante la creazione del bucket S3 nella fase 1.3.
Per Punto di accesso di supporto, specifica il nome della risorsa Amazon (ARN) del punto di accesso S3 che hai creato nella fase 3.2 utilizzando il pulsante Sfoglia S3.
Naviga verso il basso per visualizzare Configurazione della trasformazione. Nell'elenco delle API S3, seleziona l'opzione GetObject.
In Funzione Lambda, specifica ol_image_processing.
Quindi, scorri fino alla fine della pagina e scegli Crea punto di accesso Lambda dell'oggetto.
Fase 6: download delle immagini dal punto di accesso di Lambda per oggetti S3
6.1 - Apertura del punto di accesso di Lambda per oggetti S3
- Torna all'elenco dei punti di accesso di Lambda per oggetti S3 scegliendo Punti di accesso Lambda dell'oggetto nel pannello di navigazione sulla sinistra della console S3, quindi seleziona il punto di accesso di Lambda per oggetti S3 creato nella fase 5.1. In questo esempio, abbiamo il punto di accesso di Lambda per oggetti S3 come ol-amazon-s3-images-guide.
Seleziona l'immagine caricata nella fase 2.4, quindi scegli il pulsante Apri.
6.2 - Download dell'immagine trasformata dall'interfaccia a riga di comando di AWS
- Puoi scaricare l'immagine anche utilizzando AWS CLI. A tale scopo, è necessario il nome della risorsa Amazon (ARN) del punto di accesso Lambda per oggetti S3. Nella console S3, accedi alla pagina Punto di accesso Lambda dell'oggetto, seleziona il nome del punto di accesso di Lambda per oggetti S3, seleziona la scheda Proprietà e scegli l'icona di copia sotto Nome della risorsa Amazon (ARN).
6.3 - Esecuzione del comando di AWS CLI da CloudShell
Dalla scheda del browser CloudShell, inserisci quanto segue:
aws s3api get-object --bucket <paste the ARN copied above here> --key <image filename here> <filename to write here>
6.4 - Download dell'immagine sul computer locale
Da CloudShell, scegli Operazioni nell'angolo in alto a destra e seleziona Scarica file.
Inserisci il nome del file che hai definito nella fase 6.3 quando scarichi l'immagine dal punto di accesso di Lambda per oggetti S3, quindi scegli Download.
A questo punto, puoi aprire l'immagine dal tuo computer locale.
Nota: i visualizzatori di immagini possono variare in base al computer e al sistema operativo in uso. Rivolgiti al tuo amministratore se non sei sicuro dell'applicazione da usare per aprire l'immagine.
Fase 7: Eliminazione delle risorse
7.1 - Eliminazione del punto di accesso di Lambda per oggetti S3
- Accedi alla console S3 e scegli Punti di accesso Lambda dell'oggetto nel pannello di navigazione sulla sinistra.
- Nella pagina Punti di accesso Lambda dell'oggetto, scegli il pulsante di opzione sulla sinistra del punto di accesso di Lambda per oggetti S3 creato nella fase 5.1.
Seleziona Elimina.
Conferma di voler eliminare il punto di accesso di Lambda per oggetti S3 inserendone il nome nel campo di testo visualizzato, quindi scegli Elimina.
7.2 - Eliminazione del punto di accesso S3
- Nel pannello di navigazione sulla sinistra della console S3, scegli Punti di accesso.
- Vai al punto di accesso S3 creato durante la fase 3.1 e scegli il pulsante di opzione accanto al nome del punto di accesso S3.
- Seleziona Elimina.
Conferma di voler eliminare il punto di accesso inserendone il nome nel campo di testo visualizzato, quindi scegli Elimina.
7.3 - Eliminazione dell'oggetto di test
- Vai alla console S3 e seleziona l'opzione del menu Bucket nel pannello di navigazione sulla sinistra. Per prima cosa dovrai eliminare l'oggetto di test dal bucket di test. Seleziona il nome del bucket con cui hai lavorato per questo tutorial.
- Seleziona la casella di controllo a sinistra del nome dell'oggetto di prova, quindi seleziona il pulsante Elimina.
- Sulla pagina Elimina oggetti, verifica di aver selezionato l'oggetto corretto da eliminare, quindi digita delete nella casella di conferma Elimina definitivamente gli oggetti. Quindi seleziona il pulsante Elimina oggetti per continuare.
7.4 - Eliminazione del bucket S3
- Quindi, scegli Bucket dal menu della console S3 nel pannello di navigazione sulla sinistra. Seleziona il pulsante di opzione alla sinistra del bucket di origine creato per questo tutorial, quindi seleziona il pulsante Elimina.
Rivedi il messaggio di avvertenza. Se desideri continuare con l'eliminazione del bucket, digita il nome del bucket nella casella di conferma Elimina bucket, quindi seleziona Elimina bucket.
7.5 - Eliminazione della funzione Lambda
- Nella console AWS Lambda, nel pannello di navigazione sulla sinistra, scegli Funzioni.
- Seleziona la casella di controllo a sinistra del nome della funzione creata nella fase 4.3.
- Scegli Operazioni, quindi Modifica. Nella finestra di dialogo Elimina funzione, seleziona Elimina.
Conclusioni
Congratulazioni! Hai imparato a usare Lambda per oggetti Amazon S3 per aggiungere dinamicamente una filigrana a un'immagine mentre viene recuperata, restituendo l'immagine elaborata al client richiedente. Puoi personalizzare la funzione Lambda in base al tuo caso d'uso per modificare i dati restituiti dalle richieste S3 GET, HEAD e LIST, con casi d'uso comuni tra cui la personalizzazione delle filigrane utilizzando dettagli specifici del chiamante, il mascheramento dei dati sensibili, il filtraggio di determinate righe di dati, l'aumento dei dati con informazioni provenienti da altri database, la conversione dei formati di dati e molto altro.