将PIL图像对象上传到Amazon s3 python

时间:2017-09-13 18:28:38

标签: python image amazon-s3

我想从网上获取图片并将其上传到亚马逊s3。在这样做的同时,我想检查图像尺寸。 我在Python 3中有以下代码:

from PIL import Image
import requests

# Get response
response = requests.get(url, stream= True)

# Open image
im = Image.open(response.raw)

# Get size
size = im.size

# Upload image to s3
S3.Client.upload_fileobj(
    im, # This is what i am trying to upload
    AWS_BUCKET_NAME,
    key,
    ExtraArgs={
        'ACL': 'public-read'
    }
)

问题是PIL图像对象不支持读取。当我尝试上传PIL图像对象im时出现以下错误。

ValueError: Fileobj must implement read

当我尝试上传'response.raw'时它会起作用,但我需要获取图像尺寸。如何将PIL图像对象更改为类文件对象?是否有更简单的方法来获取尺寸,同时仍然能够将图像上传到s3?

所以问题是;获取图像尺寸后如何将图像上传到s3?

4 个答案:

答案 0 :(得分:11)

而不是调用read()来恢复文件内容,而是保存'该文件为真实文件对象或内存中对象之类的文件。然后在上面调用getValue()。

这是一个示例函数,您可以将文件内容传递到其中,打印出高度和宽度,然后以AWS客户端put_object函数将接受的格式返回文件数据作为Body参数。

from PIL import Image
import io

def modify_image(image, format):
    pil_image = Image.open(image)

    # Prints out (1280, 960) 
    print(pil_image.size)

    in_mem_file = io.BytesIO()

    # format here would be something like "JPEG". See below link for more info.
    pil_image.save(in_mem_file, format=format)
    return in_mem_file.getvalue()

此处还有单独的宽度和高度属性:http://pillow.readthedocs.io/en/3.4.x/reference/Image.html#attributes

在此处查看有关文件格式的更多信息http://pillow.readthedocs.io/en/3.4.x/handbook/image-file-formats.html

注意:示例使用Python 3.6.1

答案 1 :(得分:2)

您需要使用类似文件的对象,但不应调用getValue(),这与公认的答案相反。使用以下代码段,然后可以在调用in_mem_file时使用upload_fileobj将图像上传到S3:

from PIL import Image
import io

# Open image
pil_image = Image.open(response.raw)

# Save the image to an in-memory file
in_mem_file = io.BytesIO()
pil_image.save(in_mem_file, format=pil_image.format)
in_mem_file.seek(0)

# Upload image to s3
client_s3.upload_fileobj(
    in_mem_file, # This is what i am trying to upload
    AWS_BUCKET_NAME,
    key,
    ExtraArgs={
        'ACL': 'public-read'
    }
)

如果您看到上传的文件为0kB,则需要.seek(0)部分来倒回文件状对象。

答案 2 :(得分:0)

您应该使用io.BufferIO

response = requests.get(url, stream= True)
f = io.BytesIO(response.content)
image = Image.open(f)

答案 3 :(得分:0)

如果您正在使用FileStorage中的werkzeug.datastructures,并使用reqparse解析了图像,则无需将图像转换为PIL.Image,则可以在seek(0)本身上使用FileStorage

也不要忘记指定文件的Content-type

parser = reqparse.RequestParser()
parser.add_argument('image', help='image cannot be blank', type=FileStorage, 
location='files', required=True)

args = parser.parse_args()
image = args['image']

image.seek(0)
s3_client.upload_fileobj(image, self.BUCKET_NAME, filename, ExtraArgs={'ContentType': 'image/jpeg'})