【问题标题】:After uploading image to s3, upload accompanying thumbnail将图片上传到 s3 后,上传随附的缩略图
【发布时间】:2018-11-19 14:15:20
【问题描述】:

我可以通过 AJAX 成功地将我的图像上传到 s3。但是,我还需要在我的 s3 存储桶中有一个随附的缩略图。

这是我的 s3 上传 ajax 视图:

...
session = boto3.Session(
    aws_access_key_id=AWS_ACCESS_KEY_ID,
    aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
)
s3 = session.resource('s3')

s3.Bucket('****-bucket').put_object(Key='media/%s' % random_filename, Body=img, ContentType='image/png')
return HttpResponse()

从我的代码创建和上传缩略图的最佳方式是什么?我是否要在当前的下方添加另一个put_object?如果是这样,我如何实现像 PIL 这样的缩略图生成器?我试图复制this answer,但设置与我的完全不同。

或者使用 AWS lambda 函数是否可行?

任何建议表示赞赏。

编辑:

文件可以通过 2 种方法上传:来自磁盘的图像和来自 URL 的图像。文件名取自我前端生成的随机字符串。

def upload_image(request):
    random_filename = request.POST.get('random_filename')
    if request.is_ajax():
        if request.FILES:
            for file in request.FILES:
                if file == "image":
                    img = request.FILES.get('image')

        else:
            img = request.POST.get('imageURL')
            img = img_from_url(img)


        session = boto3.Session(
            aws_access_key_id=AWS_ACCESS_KEY_ID,
            aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
        )
        s3 = session.resource('s3')

        s3.Bucket('****-bucket').put_object(Key='media/%s' % random_filename, Body=img, ContentType='image/png')

def img_from_url(file):
    image_data = requests.get(file).content
    return ContentFile(image_data)

【问题讨论】:

  • 旁注:将凭证与源代码一起存储不是一个好主意。相反,在具有分配的 IAM 角色(将自动提供凭证)的 Amazon EC2 实例上运行代码或通过aws configure 创建凭证文件。
  • 凭据与源代码分开 - 在我的项目文件之外的 .env 文件夹中。

标签: python django amazon-web-services amazon-s3 python-imaging-library


【解决方案1】:

使用 OpenCV 调整图像大小并将其编码为字节,然后让 Boto3 将这些字节上传到 S3,并使用缩略图的新键名:

import boto3
import cv2

BUCKET_NAME = "MY_BUCKET_NAME"

# Load original image from disk
original_image_filename = "original_image.png"
original_image = cv2.imread(original_image_filename)

# Resize the original image to obtain a thumbnail image,
# and encode this thumbnail to bytes in the PNG format
thumbnail_image = cv2.resize(original_image, (100, 100))
thumbnail_image_png = cv2.imencode(".png", thumbnail_image)[1].tostring()

# Upload the PNG bytes of the thumbnail to S3
s3 = boto3.resource("s3")
thumbnail_image_filename = "thumbnail.png"
object = s3.Object(BUCKET_NAME, thumbnail_image_filename)
object.put(Body=thumbnail_image_png, ContentType="image/png")

【讨论】:

  • 刚刚尝试过,但在resize 行返回错误。如果你想看的话,我已经在我的编辑中添加了代码和 Traceback。
  • 好的,感谢您的反馈!我读了一点您的代码,看起来您将original_image_filename 设置为S3 URL,而cv2.imread() 将磁盘上的文件路径作为参数。确保将original_image_filename 设置为磁盘上原始图像的文件路径,然后重试。如果您有时间,我也很好奇您是如何在代码块顶部获得img 的?你能告诉我更多细节吗?
  • 不用担心。啊,有什么办法可以用 S3 URL 做到这一点?我的代码的方式是我不能真正使用磁盘文件名。我在编辑中添加了我的代码。
  • 感谢您发布完整代码。看起来您已经在image_data 中拥有原始图像的字节,因此无需从磁盘读取它们。您可以使用original_image = cv2.imdecode(image_data) 对它们进行解码,并摆脱cv2.imread() 的行。让我知道这是否有效!
  • original_image = cv2.imdecode(img) 行有一个TypeError: Required argument 'flags' (pos 2) not found。知道为什么吗?
【解决方案2】:

生成缩略图有三种基本方法(可能更多!)。

在别处生成

上传原始文件时只需上传一个附加文件。缩略图需要在系统外部生成。

使用 AWS Lambda 函数生成缩略图

当图像上传到 Amazon S3 时,它可以生成一个运行 AWS Lambda 函数的事件。然后,Lambda 函数可以创建一个新的、调整大小的图像。

例如,请参阅:Tutorial: Using AWS Lambda with Amazon S3 - AWS Lambda

使用外部服务

使用外部服务即时生成缩略图,而不是存储缩略图。一些这样的服务是:

【讨论】:

    猜你喜欢
    • 2012-03-13
    • 2011-05-08
    • 1970-01-01
    • 1970-01-01
    • 2013-05-31
    • 2015-01-05
    • 1970-01-01
    • 2016-05-23
    • 1970-01-01
    相关资源
    最近更新 更多