【问题标题】:How to compress image and then upload it to AWS S3 bucket using FastAPI?如何压缩图像然后使用 FastAPI 将其上传到 AWS S3 存储桶?
【发布时间】:2022-09-23 01:59:53
【问题描述】:

这是我将图像上传到 AWS S3 的代码:

@app.post(\"/post_ads\")
async def create_upload_files(files: list[UploadFile] = File(description=\"Multiple files as UploadFile\")):
    main_image_list = []
    for file in files:
          s3 = boto3.resource(
             \'s3\',
              aws_access_key_id =   aws_access_key_id,
               aws_secret_access_key = aws_secret_access_key
                            )
           bucket = s3.Bucket(aws_bucket_name)
           bucket.upload_fileobj(file.file,file.filename,ExtraArgs={\"ACL\":\"public-read\"}) 

有没有办法压缩图像大小并将图像上传到特定文件夹使用boto3?我有这个压缩图像的功能,但不知道如何将它集成到boto3中。

         for file in files:
                im = Image.open(file.file)
                im = im.convert(\"RGB\")
                im_io = BytesIO()
                im = im.save(im_io, \'JPEG\', quality=50)  
                
                s3 = boto3.resource(
                                \'s3\',
                                aws_access_key_id =   aws_access_key_id,
                                aws_secret_access_key = aws_secret_access_key
                            )
                bucket = s3.Bucket(aws_bucket_name)
                bucket.upload_fileobj(file.file,file.filename,ExtraArgs={\"ACL\":\"public-read\"})

更新#1

遵循克里斯的建议后,我的问题得到了解决:

这是克里斯的解决方案

im_io.seek(0)
bucket.upload_fileobj(im_io,file.filename,ExtraArgs={\"ACL\":\"public-read\"})
  • 克里斯我更新了我的问题。我修复了损坏的图像问题。现在我只想知道如何在上传 aws s3 存储桶之前压缩图像?我看到了答案,但没有正确理解。
  • @Chris 你能解释一下bucket.upload_fileobj(im_io,... 吗?是bucket.upload_fileobj(im,... 吗?
  • 克里斯我试过bucket.upload_fileobj(im_io,..,但上传后我的图片损坏了。我以前遇到过类似的问题。如果我删除我的图像压缩代码,那么我的原始图像上传没有任何问题
  • @Chris 是的,完全是零。请查看整行bucket.upload_fileobj(im_io,file.filename,ExtraArgs={\"ACL\":\"public-read\", })
  • @Chris 我试过了,但现在大小仍然为零,并且无法从 url 查看图像。我也更新了我的问题

标签: python amazon-web-services amazon-s3 boto3 fastapi


【解决方案1】:

您似乎将图像字节保存到一个从未使用过的 BytesIO 流中,因为您将原始文件对象上传到 s3 存储桶,如代码的这一行所示:

bucket.upload_fileobj(file.file, file.filename, ExtraArgs={"ACL":"public-read"}) 

因此,您需要将BytesIO 对象传递给upload_fileobj() 函数,并确保在此之前调用.seek(0),以便将光标(或“文件指针”)倒回到开头。调用.seek(0) 的原因是im.save() 方法使用游标遍历缓冲区,当到达末尾时,并没有将游标重置到开头。因此,任何未来的读取操作都将从缓冲区的末尾开始。这同样适用于从原始文件中读取,如this answer 中所述——如果文件内容已被读取并且需要再次从文件中读取,则需要调用file.file.seek(0)

如何将图像加载到BytesIO 流中并使用它来上传文件/图像的示例如下所示。请记住正确地 close fileBytesIO 对象,以释放它们的内存(参见 related answer 以及)。

try:        
    im = Image.open(file.file)
    if im.mode in ("RGBA", "P"): 
        im = im.convert("RGB")  
    buf = io.BytesIO()
    im.save(buf, 'JPEG', quality=50)
    buf.seek(0)
    bucket.upload_fileobj(buf, 'out.jpg', ExtraArgs={"ACL":"public-read"})
except Exception:
    # ...
finally:
    file.file.close()
    buf.close()
    im.close()

至于 URL,使用 ExtraArgs={"ACL":"public-read"} 应该可以按预期工作并使您的资源(文件)可以公开访问。因此,请确保您访问的是正确的 URL。

【讨论】:

    【解决方案2】:

    aws s3 同步 s3://your-pics.对于 "$ (find. -name "*.jpg")" 中的文件;做 gzip "$file";回声“$文件”;完成 aws s3 同步。 s3://your-pics --content-encoding gzip --dryrun 这会将 s3 存储桶中的所有文件下载到机器(或 ec2 实例),压缩图像文件并将它们上传回 s3 存储桶。

    这应该可以帮助你。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-18
      • 2023-03-29
      • 2017-12-23
      • 1970-01-01
      • 2018-03-11
      • 1970-01-01
      • 2019-06-12
      • 2019-08-17
      相关资源
      最近更新 更多