Upload Image using POST form data in Python-requests
Asked Answered
F

8

53

I'm working with wechat APIs ... here I've to upload an image to wechat's server using this API http://admin.wechat.com/wiki/index.php?title=Transferring_Multimedia_Files

url = 'http://file.api.wechat.com/cgi-bin/media/upload?access_token=%s&type=image'%access_token
files = {
    'file': (filename, open(filepath, 'rb')),
    'Content-Type': 'image/jpeg',
    'Content-Length': l
}
r = requests.post(url, files=files)

I'm not able to post data

Ferrol answered 17/3, 2015 at 16:8 Comment(0)
O
77

From wechat api doc:

curl -F [email protected] "http://file.api.wechat.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE"

Translate the command above to python:

import requests
url = 'http://file.api.wechat.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE'
files = {'media': open('test.jpg', 'rb')}
requests.post(url, files=files)

Doc: https://docs.python-requests.org/en/master/user/quickstart/#post-a-multipart-encoded-file

Oviposit answered 17/3, 2015 at 16:27 Comment(3)
I have issue with the comsume of an api-rest, when I try send a request, the response is "message": "No image provided in form-data request", my request is the next: curl -X POST --header "Content-Type: multipart/form-data" --head er "Accept: application/json" --header "api_key: zzzz" --header "Content-Type: image/jpg" --header "Content-Disposition: form-data" -F media=2016-09-14-154558.jpg "xxxx"Scrofulous
If someone needs to provide data as a file object, for example if you get some image like some_image = requests.get(url_to_some_image) and want to post this image to some place, you need to make an image as file object. In order to do that, based on the Kev's answer, you need to make files = {'media': io.BytesIO(some_image.content)}Dissatisfactory
hmm this isnt working for me. The request gives back a 200 code, but a response message of "None", and it is not reaching its destination. I am printing the buffer read and can confirm its grabbing the file the way you wrote by printing out the buffer strings.Rohn
T
36

In case if you were to pass the image as part of JSON along with other attributes, you can use the below snippet.
client.py

import base64
import json                    

import requests

api = 'http://localhost:8080/test'
image_file = 'sample_image.png'

with open(image_file, "rb") as f:
    im_bytes = f.read()        
im_b64 = base64.b64encode(im_bytes).decode("utf8")

headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
  
payload = json.dumps({"image": im_b64, "other_key": "value"})
response = requests.post(api, data=payload, headers=headers)
try:
    data = response.json()     
    print(data)                
except requests.exceptions.RequestException:
    print(response.text)

server.py

import io
import json                    
import base64                  
import logging             
import numpy as np
from PIL import Image

from flask import Flask, request, jsonify, abort

app = Flask(__name__)          
app.logger.setLevel(logging.DEBUG)
  
  
@app.route("/test", methods=['POST'])
def test_method():         
    # print(request.json)      
    if not request.json or 'image' not in request.json: 
        abort(400)
             
    # get the base64 encoded string
    im_b64 = request.json['image']

    # convert it into bytes  
    img_bytes = base64.b64decode(im_b64.encode('utf-8'))

    # convert bytes data to PIL Image object
    img = Image.open(io.BytesIO(img_bytes))

    # PIL image object to numpy array
    img_arr = np.asarray(img)      
    print('img shape', img_arr.shape)

    # process your img_arr here    
    
    # access other keys of json
    # print(request.json['other_key'])

    result_dict = {'output': 'output_key'}
    return result_dict
  
  
def run_server_api():
    app.run(host='0.0.0.0', port=8080)
  
  
if __name__ == "__main__":     
    run_server_api()
Trishtrisha answered 26/9, 2020 at 17:22 Comment(0)
A
16

Use this snippet

import os
import requests
url = 'http://host:port/endpoint'
with open(path_img, 'rb') as img:
  name_img= os.path.basename(path_img)
  files= {'image': (name_img,img,'multipart/form-data',{'Expires': '0'}) }
  with requests.Session() as s:
    r = s.post(url,files=files)
    print(r.status_code)
Arturoartus answered 19/2, 2019 at 22:5 Comment(2)
U sir r a geniusPhillie
What role does Expires play?Phillie
M
11

I confronted similar issue when I wanted to post image file to a rest API from Python (Not wechat API though). The solution for me was to use 'data' parameter to post the file in binary data instead of 'files'. Requests API reference

data = open('your_image.png','rb').read()
r = requests.post(your_url,data=data)

Hope this works for your case.

Memnon answered 3/7, 2018 at 6:48 Comment(1)
Thank you. This solution worked for me. using requests.post to send data. picture_doc = f'{file_path}/{file_name}' file = {file: open(picture_doc, 'rb').read()} requests.post (url, path=path, data = data, files=file)Oahu
E
8
import requests

image_file_descriptor = open('test.jpg', 'rb')
# Requests makes it simple to upload Multipart-encoded files 
files = {'media': image_file_descriptor}
url = '...'
requests.post(url, files=files)
image_file_descriptor.close()

Don't forget to close the descriptor, it prevents bugs: Is explicitly closing files important?

Euphorbiaceous answered 4/12, 2018 at 8:14 Comment(2)
Where does your files come from?Nubbin
Use with open('test.jpg', 'rb') as image file_descriptor:.Cozza
S
3

This works for me.

import requests

url = "https://example.com"
payload={}
files=[
  ('file',('myfile.jpg',open('/path/to/myfile.jpg','rb'),'image/jpeg'))
]

response = requests.request("POST", url, auth=("my_username","my_password"), data=payload, files=files)
print(response.text)
Sisterhood answered 25/5, 2022 at 10:7 Comment(0)
C
3

If you have CURL then you can directly get request from Postman.

import requests

url = "your URL"

payload={}
files=[
  ('upload_file',('20220212235319_1509.jpg',open('/20220212235319_1509.jpg','rb'),'image/jpeg'))
]
headers = {
  'Accept-Language': 'en-US',
  'Authorization': 'Bearer yourToken'
}

response = requests.request("POST", url, headers=headers, data=payload, files=files)

print(response.text)
Carlynne answered 27/5, 2022 at 4:29 Comment(0)
A
1

For Rest API to upload images from host to host:

import urllib2
import requests

api_host = 'https://host.url.com/upload/'
headers = {'Content-Type' : 'image/jpeg'}
image_url = 'http://image.url.com/sample.jpeg'

img_file = urllib2.urlopen(image_url)

response = requests.post(api_host, data=img_file.read(), headers=headers, verify=False)

You can use option verify set to False to omit SSL verification for HTTPS requests.

Ailurophile answered 14/9, 2018 at 8:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.