Image upload issue - Python

Hello,

I am just trying to post an image, and following the documentation available for the admin api:

When I see the curl:

curl -X POST -F 'file=@/path/to/images/my-image.jpg' -F 'ref=path/to/images/my-image.jpg' -H "Authorization: 'Ghost $token'" -H "Accept-Version: $version" https://{admin_domain}/ghost/api/admin/images/upload/

It translates to:

import os

import requests

token' = os.getenv('token'')
version = os.getenv('version')

headers = {
    'Authorization': f"'Ghost {token'}",
    'Accept-Version': f"{version}",
}

files = {
    'file': open('/path/to/images/my-image.jpg', 'rb'),
    'ref': (None, 'path/to/images/my-image.jpg'),
}

response = requests.post('https://{admin_domain}/ghost/api/admin/images/upload/', headers=headers, files=files)

In python,
There is already a difference between the ref in the curl and the one in the documentation.

Whatever I try, my best result is a 415 error code:

'{"errors":[{"message":"Please select a valid image.","context":null,"type":"UnsupportedMediaTypeError","details":null,"property":null,"help":null,"code":null,"id":"46fff9b0-ecb1-11ec-9c4b-e5f617404273"}]}'

I tried both jpg and png. I saw different things online, but I guess they were linked to other version of the api.

EDIT1:

I forgot indeed the content-type header.
If i go with

    headers = {'Authorization': 'Ghost {}'.format(token),
               'Accept-Version': "v1",
               'Content-Type': 'multipart/form-data;'}

I now get a Error code 422:

{"message":"Please select an image.","context":null,"type":"ValidationError"

Thanks in advance!

Curl automatically sets the mime type header for some file extensions. If your language/library of choice does not do the same then you’ll need to set the type header manually

Some further info on Curls behaviour can be found in this question How does `curl` on the command line determine the MIME type of a file being uploaded? - Unix & Linux Stack Exchange

1 Like

Thank you for your prompt answer.
I edited the question with the updated header, as per the documentation indeed, adding the multiform/part-data type.

But I still get another error.

Any idea of the correct way to upload an image using Python?

Thanks

@Benoit_Baylin Did you get any solution for that? I am facing a similar issue.

Hey did you get any solution?

I am facing the same issue:

{“errors”:[{“message”:“Please select an image.”,“context”:null,“type”:“ValidationError”,“details”:null,“property”:null,“help”:null,“code”:null,“id”:“658e71a0-f7c7-11ed-a43a-35330461017c”,“ghostErrorCode”:null}]}

For future reference, this codes works for me:

import requests # pip install requests
import jwt	# pip install pyjwt
from datetime import datetime as date

# Admin API key goes here
key = ''

# Split the key into ID and SECRET
id, secret = key.split(':')

# Prepare header and payload
iat = int(date.now().timestamp())

header = {'alg': 'HS256', 'typ': 'JWT', 'kid': id}
payload = {
    'iat': iat,
    'exp': iat + 5 * 60,
    'aud': '/admin/'
}

# Create the token (including decoding secret)
token = jwt.encode(payload, bytes.fromhex(secret), algorithm='HS256', headers=header)

# Make an authenticated request to create a post

url = 'https://ghost.test.com/ghost/api/admin/images/upload/'
headers = {'Authorization': 'Ghost {}'.format(token)}

with open("test.jpg", "rb") as file:
	files = {'file': ('test.jpg', file, 'image/jpeg')}
	r = requests.post(url, files=files, headers=headers)

print(r.json())

It seems to be important to explicitely set the MIME type, as to image/jpeg in this example. I still had to install the sharp image processing library to make upload with python work.