使用 Boto3 在 Python 中将 base64 字符串(图像数据)上传到 S3 服务器并获取 URL 作为回报

Kar*_*rma 8 python amazon-s3 amazon-web-services python-3.x boto3

我正在尝试使用 Python 上传一个 base 64 string ,它基本上是图像数据到 S3 存储桶。我用谷歌搜索并得到了一些答案,但没有一个对我有用。有些答案使用 boto 而不是 boto3,因此它们对我来说毫无用处。我也试过这个链接:Boto3:将文件从 base64 上传到 S3,但它对我不起作用,因为Objects3 不知道该方法。

以下是我到目前为止的代码:

import boto3

s3 = boto3.client('s3')
filename = photo.personId + '.png'
bucket_name = 'photos-collection'
dataToPutInS3 = base64.b64decode(photo.url[23:])
Run Code Online (Sandbox Code Playgroud)

将此变量dataToPutInS3数据上传到 s3 存储桶并从中获取 url的正确方法是什么。

p8u*_*8ul 13

您可以将 base64 转换为 IO 字节并用于upload_fileobj上传到 S3 存储桶。

import base64
import six
import uuid
import imghdr
import io


def get_file_extension(file_name, decoded_file):
    extension = imghdr.what(file_name, decoded_file)
    extension = "jpg" if extension == "jpeg" else extension
    return extension


def decode_base64_file(data):
    """
    Fuction to convert base 64 to readable IO bytes and auto-generate file name with extension
    :param data: base64 file input
    :return: tuple containing IO bytes file and filename
    """
    # Check if this is a base64 string
    if isinstance(data, six.string_types):
        # Check if the base64 string is in the "data:" format
        if 'data:' in data and ';base64,' in data:
            # Break out the header from the base64 content
            header, data = data.split(';base64,')

        # Try to decode the file. Return validation error if it fails.
        try:
            decoded_file = base64.b64decode(data)
        except TypeError:
            TypeError('invalid_image')

        # Generate file name:
        file_name = str(uuid.uuid4())[:12]  # 12 characters are more than enough.
        # Get the file name extension:
        file_extension = get_file_extension(file_name, decoded_file)

        complete_file_name = "%s.%s" % (file_name, file_extension,)

        return io.BytesIO(decoded_file), complete_file_name


def upload_base64_file(base64_file):
    bucket_name = 'your_bucket_name'
    file, file_name = decode_base64_file(base64_file)
    client = boto3.client('s3', aws_access_key_id='aws_access_key_id',
                          aws_secret_access_key='aws_secret_access_key')

    client.upload_fileobj(
        file,
        bucket_name,
        file_name,
        ExtraArgs={'ACL': 'public-read'}
    )
    return f"https://{bucket_name}.s3.amazonaws.com/{file_name}"
Run Code Online (Sandbox Code Playgroud)


Ami*_*nes 11

你没有提到你如何获得base64。为了重现,我的代码片段使用requests库从互联网获取图像,然后使用库将其转换为 base64 base64

这里的技巧是确保您要上传的 base64 字符串不包含data:image/jpeg;base64前缀。而且,正如@dmigo 在评论中提到的,您应该使用boto3.resource而不是 boto3.client。

    from botocore.vendored import requests
    import base64
    import boto3

    s3 = boto3.resource('s3')
    bucket_name = 'BukcetName'
    #where the file will be uploaded, if you want to upload the file to folder use 'Folder Name/FileName.jpeg'
    file_name_with_extention = 'FileName.jpeg'
    url_to_download = 'URL'

    #make sure there is no data:image/jpeg;base64 in the string that returns
    def get_as_base64(url):
        return base64.b64encode(requests.get(url).content)

    def lambda_handler(event, context):
        image_base64 = get_as_base64(url_to_download)
        obj = s3.Object(bucket_name,file_name_with_extention)
        obj.put(Body=base64.b64decode(image_base64))
        #get bucket location
        location = boto3.client('s3').get_bucket_location(Bucket=bucket_name)['LocationConstraint']
        #get object url
        object_url = "https://%s.s3-%s.amazonaws.com/%s" % (bucket_name,location, file_name_with_extention)
        print(object_url)
Run Code Online (Sandbox Code Playgroud)

更多关于S3.Object.put