0

This is the first question I've asked on here so excuse any inexperience :-)

I have the following file for saving images and then returning me the file path/URL:

import os, requests
import secrets
from PIL import Image
from flask import url_for, current_app

def save_picture(google_url):
    random_hex = secrets.token_hex(8)
    i = Image.open(requests.get(google_url, stream=True).raw)
    f_ext = (i.format).lower()
    picture_fn = random_hex + f_ext
    picture_path = os.path.join(current_app.root_path, 'static/experience_images', picture_fn)

    output_size = (600, 600)
    i.thumbnail(output_size)
    i.show()
    i.save(picture_path)

    return picture_fn

I am getting the following error

raise ValueError("unknown file extension: {}".format(ext))

The google_url parameter is a api URL to get an image from Google Places API. Below when I call i.show() the image opens up so I know the image is coming through, and I can see that in most cases (though not necessarily all) it is returning a PNG or JPEG file. I think the issue is that I'm not actually getting any filename from i, and I am assuming this is because it's a tempfile.

Any help would be greatly appreciated, I'm a bit of a newbie to Python.

Emmet Gibney
  • 113
  • 1
  • 9
  • Possible duplicate of [How can I check the extension of a file?](https://stackoverflow.com/questions/5899497/how-can-i-check-the-extension-of-a-file) – Prudhvi Oct 19 '19 at 15:58

3 Answers3

1

This is a guess, because I don't a Google Places account, however: generally, HTTP responses will declare the type of data that they contain in the content type header.

The header's value might look like this

"image/jpeg"

or this

"image/jpeg; charset=UTF-8"

The mimetypes module in the standard library contains tools to derive the extenstion from this header value. So you could do something like this:

import mimetypes
import requests

def save_picture(google_url):

    response = requests.get(google_url, stream=True)
    content_type = response.headers['content-type']    # 'image/jpeg; charset=UTF-8'
    mimetype, _, _ = content_type.partition(';')       # 'image/jpeg'
    f_ext = mimetypes.guess_extension(mimetype)        # '.jpg'

    random_hex = secrets.token_hex(8)
    i = Image.open(response.raw)
    picture_fn = random_hex + f_ext
    picture_path = os.path.join(current_app.root_path, 'static/experience_images', picture_fn)

    output_size = (600, 600)
    i.thumbnail(output_size)
    i.show()
    i.save(picture_path)

    return picture_fn
snakecharmerb
  • 47,570
  • 11
  • 100
  • 153
0

According to the PIL documentation the format string may be None under certain circumstances. (It would be helpful if you would post a complete example that I can run in a notebook and play with, if I use a random image URL it basically works.)

It might be enough to provide a default format (.jpg?) f_ext = (i.format).lower() if i.format is not None else '.jpg' for those cases, but guessing a bit here...

DrD
  • 551
  • 2
  • 8
0

Ok so I have figured out a solution. If others have a better solution I am all ears.

Basically what seems to have been the problem is when I get the file extension type using i.format it doesn't include the '.' in '.PNG'. So The filename was something like 'filenamepng' instead of 'filename.png'.

So now after getting the file extension with

f_ext = i.format

I create the filename with

picture_fn = random_hex + '.' + f_ext

Now everything seems to work :-) Thanks to DrD, I figured this out while putting together a sample code snippet for you to try out.

The completed code now is as follows:

import os, requests
import secrets
from PIL import Image
from flask import url_for, current_app

def save_picture(google_url):
    random_hex = secrets.token_hex(8)
    i = Image.open(requests.get(google_url, stream=True).raw)
    f_ext = (i.format).lower()
    picture_fn = random_hex + '.' + f_ext
    picture_path = os.path.join(current_app.root_path, 'static/experience_images', picture_fn)

    output_size = (600, 600)
    i.thumbnail(output_size)
    i.save(picture_path)

    return picture_fn
Emmet Gibney
  • 113
  • 1
  • 9