使用Python在POST请求中发送多个PIL图像的StringIO

3
我在电脑上存了一张图片。使用 Python Image模块 打开它。然后,我使用该模块将此图像裁剪成几个部分。最后,我想通过POST请求将图像上传到网站。
因为小图片是PIL对象,所以我将它们中的每一个转换为StringIO,以便能够发送表单而无需将它们保存在我的电脑上。
不幸的是,我遇到了错误,而如果这些图片实际存储在我的电脑上,就没有问题。我不明白为什么会这样。
您可以访问此网站:http://www.noelshack.com/api.php 这是一个非常基本的API,返回上传图片的链接。 在我的情况下,问题在于第二张图片结束时没有返回任何内容(第一张没有问题)。
这是将图像分割成100个部分的编程代码。
import requests
import Image
import StringIO
import os

image = Image.open("test.jpg")
width, height = image.size

images = []

for i in range(10):
    for j in range(10):
        crop = image.crop((i * 10, j * 10, (i + 1) * 10, (j + 1) * 10))
        images.append(crop)

上传图像的函数:
def upload(my_file):
    api_url = 'http://www.noelshack.com/api.php'
    r = requests.post(api_url, files={'fichier': my_file})

    if not 'www.noelshack.com' in r.text:
        raise Exception(r.text)

    return r.text

现在我们有两种可能性。第一种是将这100张图片保存在磁盘上并上传它们。
if not os.path.exists("directory"):
    os.makedirs("directory")

i = 0
for img in images:
    img.save("directory/" + str(i) + ".jpg")
    i += 1

for file in os.listdir("directory"):
    with open("directory/" + file, "rb") as f:
        print upload(f)

它的工作非常好,但不是很方便。因此,我想使用StringIO。

for img in images:
    my_file = StringIO.StringIO()
    img.save(my_file, "JPEG")
    print upload(my_file.getvalue())
    # my_file.close() -> Does not change anything

第一个链接被打印出来了,但是函数随后引发了异常。

我认为问题在于 img.save(),因为同样类型的for循环不能保存到磁盘然后上传。此外,如果在上传之间添加 time.sleep(1),似乎可以解决问题。

如有任何帮助,请提供,因为我真的陷入了困境。


在第一个物理文件案例中,您正在向 upload() 传递已打开的图像 file 对象;在第二个 StringIO 案例中,您正在将图像文件的数据内容传递给它。 - martineau
@martineau 我该怎么办?为什么第二种情况对于一两张图片有效,然后就会引发异常? - Delgan
如果你只是传递一个名为my_fileStringIO对象,它可能会起作用,因为前者大多像常规的file对象一样运作。 - martineau
在将虚拟文件传递给“upload()”之前,您可能需要使用“my_file.seek(0)”倒回虚拟文件。 - martineau
@martineau 也尝试过了,但是没有起作用。添加 time.sleep(1) “解决”问题很奇怪,我无法解释。 - Delgan
显示剩余2条评论
1个回答

2

my_file.getvalue()返回一个字符串。你需要的是一个类似文件的对象,而my_file已经是一个类似文件的对象了。文件类似对象有一个光标,可以说是指示从哪里读取或写入。因此,在上传之前,如果你执行my_file.seek(0),它应该就能被修复了。

修改代码为:

for img in images:
    my_file = StringIO.StringIO()
    img.save(my_file, "JPEG")
    my_file.seek(0)
    print upload(my_file)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接