使用Python通过POST请求发送多个PIL Image的StringIO

3 投票
1 回答
2200 浏览
提问于 2025-04-18 09:58

我在电脑上有一张存储的图片。我用 Python图像模块 打开它。接着,我用这个模块把这张图片裁剪成几块。最后,我想通过一个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() 上,因为同样的循环在保存到磁盘然后上传时也不工作。此外,如果在上传之间加上 time.sleep(1),似乎就能正常工作。

任何帮助都非常欢迎,因为我真的卡住了。

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)

撰写回答