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

Principiante.

 Tempo per il completamento

20 minuti

 Costo richiesto per il completamento

 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: 

Implementazione

Fase 1: Creazione di un bucket Amazon S3

1.1 - Accesso alla console 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

Ora che il bucket è stato creato e configurato, sei pronto per caricare un'immagine.

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

Crea un punto di accesso di Lambda per oggetti S3 che verrà utilizzato per accedere alle immagini archiviate nel tuo bucket S3.

5.1 - Creazione del punto di accesso di Lambda per oggetti S3

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

Dopo aver creato il punto di accesso di Lambda per oggetti S3, apriremo l'immagine per verificare che durante la richiesta la filigrana sia stata aggiunta correttamente.

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.

Si aprirà una nuova scheda del browser con l'immagine e una filigrana.
 
Tutte le immagini compatibili scaricate dal punto di accesso di Lambda per oggetti S3 ora includeranno il testo con la filigrana.


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

Nelle fasi successive, effettuerai la pulizia delle risorse create in questo tutorial. Per evitare di ricevere addebiti non desiderati, una best practice consiste nell'eliminare le risorse non più utilizzate.

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.
Successivamente, verrà visualizzato un banner che indica se l'eliminazione è andata a buon fine.

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.

Questa pagina è stata utile?

Fasi successive