调整大小后,Lambda将图像从一个存储桶复制到另一个存储桶

时间:2020-05-14 10:50:06

标签: amazon-web-services amazon-s3 aws-lambda

我正在S3存储桶上接收图像。我想使用lambda函数将图像调整为缩略图大小,然后将缩略图复制到另一个s3存储桶中。以下是代码:

import json
import boto3
import ast
from urllib.request import urlopen
import time
from boto3.dynamodb.conditions import Key, Attr
from PIL import Image

s3_client=boto3.client('s3')
s3_res = boto3.resource('s3')
def lambda_handler(event, context):
    client = boto3.resource("dynamodb")
    tnlBuck = s3_res.Bucket('aivuthumbnail')
    for record in event['Records']:
        bucket=record['s3']['bucket']['name']
        ikey = record['s3']['object']['key']
        params = {'Bucket': bucket, 'Key': ikey}
        proj = ikey.split('_')[0]
        outlet = ikey.split('_')[1]
        parameter = ikey.split('_')[2]
        dat = ikey.split('_')[3]
        table = client.Table("telescopeImageReceipt")
        table.put_item(Item={'image':ikey,'project':proj,'outlet':outlet,'parameter':parameter,'date':dat})
        url = s3_client.generate_presigned_url(ClientMethod='get_object', Params=params)
        with urlopen(url) as conn:
            image = Image.open(conn)
            MAX_SIZE = (100, 100) 
            image.thumbnail(MAX_SIZE)
            image.copy("Bucket":tnlBuck)

我已将最后一行更改为各种组合。但是没有任何效果。 lambda函数具有对S3,Dynamodb和Cloudwatch日志的完全访问权限。

以下是我尝试并得到错误消息的一些选项:

Option Tried:  tnlBuck.copy(image, ikey)
Error : Expecting dictionary formatted: {"Bucket": bucket_name, "Key": key} but got <PIL.JpegImagePlugin.JpegImageFile image

Option Tried: s3_client.copy({"Bucket":tnlBuck, "Key":ikey})
Error:  TypeError: copy() missing 2 required positional arguments: 'Bucket' and ‘Key'

Option tried:  image.copy({"Bucket":tnlBuck, "Key":ikey})
Error:  TypeError: copy() takes 1 positional argument but 2 were given

其他选项或多或少有相似的错误或抛出了syntax error

1 个答案:

答案 0 :(得分:1)

您需要使用S3存储桶将映像复制到其中,而不是 PIL Image 对象。 您的代码应更改为此:

import json
import io
import boto3
import ast
from urllib.request import urlopen
import time
from boto3.dynamodb.conditions import Key, Attr
from PIL import Image

s3_client=boto3.client('s3')
s3_res = boto3.resource('s3')
def lambda_handler(event, context):
    client = boto3.resource("dynamodb")
    tnlBuck = s3_res.Bucket('aivuthumbnail')
    for record in event['Records']:
        bucket=record['s3']['bucket']['name']
        ikey = record['s3']['object']['key']
        params = {'Bucket': bucket, 'Key': ikey}
        proj = ikey.split('_')[0]
        outlet = ikey.split('_')[1]
        parameter = ikey.split('_')[2]
        dat = ikey.split('_')[3]
        table = client.Table("telescopeImageReceipt")
        table.put_item(Item={'image':ikey,'project':proj,'outlet':outlet,'parameter':parameter,'date':dat})
        url = s3_client.generate_presigned_url(ClientMethod='get_object', Params=params)
        with urlopen(url) as conn:
            image = Image.open(conn)
            MAX_SIZE = (100, 100) 
            image.thumbnail(MAX_SIZE)
            img_bytes = io.BytesIO()
            image.save(img_bytes, format='JPEG')
            img_bytes.seek(0)
            tnl_bucket.Object(ikey).put(Body=img_bytes.read())

您应该使用 tnl_bucket 从缩略图图像字节创建新对象。

img_bytes = io.BytesIO()
image.save(img_bytes, format='JPEG')
img_bytes.seek(0)
tnl_bucket.Object(ikey).put(Body=img_bytes.read())

PIL可以保存到path或BytesIO上的文件。您需要返回以 .seek(0)开头的流,以便可以从头开始读取它以获取 put 方法的字节。