【问题标题】:How to approach html file inputs to S3 without pre-signed URLs如何在没有预签名 URL 的情况下处理对 S3 的 html 文件输入
【发布时间】:2020-11-17 16:39:11
【问题描述】:

假设我有一个表单,用户可以在其中提交图像文件,然后我想将它们发布到我的 AWS S3 存储桶。我不想直接使用pre-signed URLs 传递它们,因为我正在压缩/修改图像。

如果我先将它们保存到我的文件系统然后使用 s3_client.upload_file 并从文件系统中获取图像可以吗?

问题是,我在 Heroku 上托管我的网站,它与临时文件系统一起使用,并且在某些时候,图像将从我的静态文件夹中消失。但是,在这种情况下,我将此作为一个优势,因为只有在我完成将图像上传到我的 S3 存储桶时,我才需要文件系统中的图像。这是一个好方法吗?

代码

如果我尝试s3_client.upload_file 而我的文件系统中还没有图像,客户端将抛出错误。

with Image.open(image) as i:
    i = Image.open(image)
    
    # If the image is for background, create multiple sizes.
    if is_background:
        img_1920_1920 = i.resize((1920, 1920), Image.LANCZOS)
        img_400_400 = i.resize((800, 533), Image.LANCZOS)

        # Add images to s3 bucket
        current_app.s3_client.upload_file(safe_filename, current_app.config['AWS_BUCKET_NAME'], os.path.join(image_path, '1920_1920/', safe_filename))
        current_app.s3_client.upload_file(safe_filename, current_app.config['AWS_BUCKET_NAME'], os.path.join(image_path, '800_533/', safe_filename))

可能的解决方案

我尝试这样做,但我不知道考虑到这种情况(网站托管在 Heroku 上)是否是一种好习惯。

  • 压缩/修改图像并将它们保存到文件系统
  • 完成压缩后立即将它们发布到 AWS S3
with Image.open(image) as i:
    i = Image.open(image)
    
    # If the image is for background, create multiple sizes.
    if is_background:
        img_1920_1920 = i.resize((1920, 1920), Image.LANCZOS)
        img_400_400 = i.resize((800, 533), Image.LANCZOS)

        # Save images in filesystem
        img_1920_1920.save( os.path.join(image_path, '1920_1920/', safe_filename), optimize=True, quality=85)
        img_400_400.save( os.path.join(image_path, '800_533/', safe_filename), optimize=True, quality=85)

        # Add images to s3 bucket
        current_app.s3_client.upload_file(os.path.join(image_path, '1920_1920/', safe_filename), current_app.config['AWS_BUCKET_NAME'], os.path.join(image_path, '1920_1920/', safe_filename))
        current_app.s3_client.upload_file(os.path.join(image_path, '800_533/', safe_filename), current_app.config['AWS_BUCKET_NAME'], os.path.join(image_path, '800_533/', safe_filename))

【问题讨论】:

    标签: python amazon-web-services flask heroku amazon-s3


    【解决方案1】:

    您的解决方案对我来说似乎非常合理,我在我工作过的一些系统上做了类似的事情 - 上传首先进入网站的文件系统(在我的情况下为 ec2),进行一些上传后处理,然后移动生成的文件到 s3。

    如果您想完全绕过使用本地文件系统,您通常会这样做:

    1. 使用预签名的 url 直接上传到 s3
    2. s3 事件通知通知 aws lambda 新文件已到达
    3. 用于执行上传后处理的自定义 lambda 代码

    我也使用了上述方法,但它确实增加了一些复杂性,这是一个缺点,但如果您同时进行大量上传,通常会更好地扩展。

    也就是说,从简单的解决方案开始,仅在需要时/在需要时进行扩展。

    【讨论】:

    猜你喜欢
    • 2021-02-25
    • 2018-12-15
    • 2018-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-12
    相关资源
    最近更新 更多