【问题标题】:Lambda Copy Image from one bucket to another after resize调整大小后,Lambda 将图像从一个存储桶复制到另一个存储桶
【发布时间】:2020-05-15 17:55:48
【问题描述】:

我在 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

【问题讨论】:

  • 错误是什么?
  • 添加了错误信息
  • 试试这个:gist.github.com/jangia/87606ee41665b2a061869a728ea19ca4如果它没有帮助你可以在推特上联系我,我可以帮助你。
  • @JanGiacomelli 非常感谢...代码运行良好。我做了一些更改 1. 添加了 import io 库和 2. 将 0 的第一个索引传递到 img_bytes.seek() 。再次感谢你。我可以接受答案。
  • 太棒了。今天晚些时候会写一个答案

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


【解决方案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 可以保存到路径或 BytesIO 上的文件。您需要返回以 .seek(0) 开头的流,以便可以从头开始读取它以获取 put 方法的字节。

【讨论】:

    猜你喜欢
    • 2013-11-01
    • 2020-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-17
    • 2018-11-22
    • 1970-01-01
    相关资源
    最近更新 更多