Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Send multiple StringIO from PIL Image in POST requests with Python

I have a stored picture on my computer. I open it using the Python Image module. Then I crop this image into several pieces using this module. To conclude, I would like to upload the image via a POST request on a website.

Because that small images are PIL object, I converted each of them into StringIO to be able to send the form without having to save them on my PC.

Unfortunately, I encounter an error, whereas if the images are physically stored on my PC, there is no problem. I do not understand why.

You can visit the website here: http://www.noelshack.com/api.php This is a very basic API that returns the link to the uploaded picture. In my case, the problem is that returns nothing, at the end of the second image (no problem for the first).


Here is the programming code to crop the image into 100 pieces.

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)

The function to upload an image:

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

Now we have two possibilities. The first is to save each of the 100 images on disk and upload them.

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)

It works like a charm, but it is not very convenient. So, I thought to use 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

The first link is printed, but the function raise the exception then.

I think the problem lies in the img.save(), because the same kind of for loop was not working to save to disk and then upload. In addition, if you add a time.sleep(1) between the uploads, it seems to work.

Any help would be welcome please, because I'm really stuck.

like image 284
Delgan Avatar asked Aug 07 '26 09:08

Delgan


1 Answers

my_file.getvalue() returns a string. What you need is a file-like object, which my_file already is. And file like objects have a cursor, so to speak, which says where to read from or write to. So, if you do my_file.seek(0) before the upload, it should get fixed.

modify the code to:

for img in images:
    my_file = StringIO.StringIO()
    img.save(my_file, "JPEG")
    my_file.seek(0)
    print upload(my_file)
like image 186
sudP Avatar answered Aug 08 '26 23:08

sudP



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!