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

将PIL图像对象上载到Amazon s3 python,python,image,amazon-s3,Python,Image,Amazon S3,我想从网络上获取一张图片并上传到AmazonS3。在执行此操作时,我想检查图像尺寸。 我在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

我想从网络上获取一张图片并上传到AmazonS3。在执行此操作时,我想检查图像尺寸。 我在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?

您应该使用
io.BufferIO

response = requests.get(url, stream= True)
f = io.BytesIO(response.content)
image = Image.open(f)
不是调用read()来取回文件内容,而是将文件“保存”到内存中的真实文件对象或类似文件的对象。然后对其调用getValue()

下面是一个示例函数,您可以将文件内容传递到其中,打印出高度和宽度,然后以AWS客户端put_对象函数将接受为主体参数的格式返回文件数据

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()
此处还有单独的宽度和高度属性:

请在此处查看有关文件格式的更多信息


注意:示例使用Python 3.6.1

您需要使用类似文件的对象,但与公认的答案相反,您不应该调用
getValue()
。使用以下代码段,您可以在调用
upload\u fileobj
时使用\u mem\u file中的
将图像上载到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)
部分倒带类似文件的对象。

如果您使用
werkzeug.datastructures
中的
文件存储
,使用
reqparse
解析图像,则无需将图像转换为
PIL.image
,您可以在
FileStorage
本身上使用
seek(0)

另外,不要忘记指定文件的
内容类型

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'})

这不会改变任何事情。图像打开良好。当我想将图像上载到s3时出现问题。您是否尝试将
f
加载到aws中?用
f
代替
im
是的,我试过了。首先,
response
没有一个名为
read
的属性,我假设你的意思是
response.raw.read()
。当我尝试这样做时,我上传了一个空文件,因为当它用Image.open()打开时,
f
已经被清空了。从响应中尝试
content
attr怎么样?它仍然只是上传一个空图片。如果我删除
Image.open(f)
part所有部分都可以。只是对下一个家伙唠叨:
format=format
应该是
format=pil\u Image.format
这是准确的答案。谢谢你提供这个。我在尝试被接受的答案,对自己做错的事情有点不知所措。这真的很有帮助。