Upload Image using POST form data in Python-requests - python

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

From wechat api doc:
curl -F media=#test.jpg "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

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()

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)

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.

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?

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.

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)

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)

Related

Shazam detect API throws a HTTP 406 Not Acceptable

I'm trying to test the Shazam API Detect feature on a mono sample as provided by this tutorial.
My code reads the raw audio file and sends it as base64 plaintext in the body of a POST requests to the Shazam API.
The audio file can be downloaded via this link:
import requests
import base64
def shazam(payload):
url = "https://shazam.p.rapidapi.com/songs/detect"
payload = open(payload,"rb").read()
payload = base64.b64encode(payload)
payload = str(payload)
headers = {
'x-rapidapi-host': "shazam.p.rapidapi.com",
'x-rapidapi-key':str(open("./api.txt","r").read().strip()),
'content-type': "text/plain",
'accept': "text/plain"
}
response = requests.request("POST", url, data=payload, headers=headers)
print(response.text)
shazam("/home/samples/mono.raw")
Any ideas where I'm going wrong?
I'am having problems with this API as well been searching up and down to find a solution :(
it work on me
from pydub import AudioSegment
import base64
import requests
import json
file_path="./test.raw"
url = "https://rapidapi.p.rapidapi.com/songs/detect"
encode_string = base64.b64encode(open(file_path, "rb").read())
payload=encode_string
print(type(payload))
headers = {
'content-type': "text/plain",
'x-rapidapi-key': "<<<you key>>>",
'x-rapidapi-host': "shazam.p.rapidapi.com"
}
response = requests.request("POST", url, data=payload, headers=headers)
print(json.dumps(json.loads(response.text)))

Saving Response from Requests to a file

Im using postman to call an API. The use case i have is I need to call the api using the Python-Requests and add error handling and e-mail confirmation. The response i get should be written to a file. Im completely new to python and does not have any expertise. Can someone help?
This is the python Requests code i have
import requests
url = "http://XXXX"
payload = {}
headers= {}
response = requests.request("GET", url, headers=headers, data = payload)
print(response.text.encode('utf8'))
You can write it to a file by doing this:
import requests
url = "http://XXXX"
payload = {}
headers= {}
response = requests.request("GET", url, headers=headers, data = payload)
f = open('dir here', 'w')
f.write(response.text.encode('utf8'))
f.close()
import requests
url = "http://XXXX"
payload = {}
headers= {}
response = requests.request("GET", url, headers=headers, data = payload)
print(response.text.encode('utf8'))
file = open("file_location.csv", 'a')
save = f"{response.text.encode('utf8')}"
file.write(save)
file.close()

Uploading a file to Marketo using a Dropbox link to the file

I am using the python code below to upload a file to our marketing automation tool Marketo. It works when I have the file downloaded locally (/home/tyron/Downloads/yoda.jpeg) but I would like to be able to upload a file straight from Dropbox to Marketo without having to download it inbetween because I will be hosting this code in Zapier.
What is the best way to do this upload when given a link to the dropbox file?
import requests
url = "xxxxxx/rest/asset/v1/files.json"
payload = {'name': 'test',
'file': '/home/tyron/Downloads/yoda.jpe',
'folder': '{"id":367,"type":"Folder"}'}
files = [
('file', open('/home/tyron/Downloads/yoda.jpeg','rb'))
]
headers = {
'Authorization': 'Bearer yyyyyyyy'
}
response = requests.request("POST", url, headers=headers, data = payload, files = files)
print(response.text.encode('utf8'))
Thanks to Greg's suggestion in the comments I was able to upload the file to Marketo using the temporary link endpoint from dropbox.
Python Code to Get Dropbox Endpoint
import re
from urllib.parse import urlparse
from urllib.parse import unquote
import requests
import json
link = "https://www.dropbox.com/preview/Telnyx/...../file"
path = urlparse(link).path
path = re.search("(/Telnyx.*$)",path).group(0).lower()
path = unquote(path)
print(path)
url = "https://api.dropboxapi.com/2/files/get_temporary_link"
payload = {"path": path}
headers = {
'Authorization': 'Bearer xxxxxxxxxxxxxx',
'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data = json.dumps(payload))
print(response)
link = re.search('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_#.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', response.text).group(0)
return {'id': 1234, 'rawHTML': link}
Python Code to Upload to Marketo
import requests
import urllib
import json
import re
path = "https://dl.dropboxusercontent.com/apitl/1/......." #returned from previous function
f = urllib.request.urlopen(path)
mime_type = f.info().get_content_type()
f_ext = f.info().get_content_type().split("/")[1]
url = "https://xxx-xxx-xxx.mktorest.com/rest/asset/v1/files.json"
f_name = 'Name.' + f_ext
payload = {
'folder': '{"id":xxxx","type":"Folder"}'
}
headers = {
'Authorization': 'Bearer xxxxxxxx'
}
files = {'file': (f_name, f, mime_type)}
response = requests.request("POST", url, headers=headers, data = payload, files = files)
print(response.text.encode('utf8'))
f_url = re.search('"url":"(.*)","folder',response.text).group(1)
return {'id': 1234, 'rawHTML': f_url}

POST pdf-file is not received by API, Python, Requests

So I built an API which takes in a pdf file and json and converts the file into text. Testing with Postman works fine, however now I try to make a script to send multiple images and the API does not receive the image I send it in the script. It receives the request but not its contents. Additionally I don't get the json file either, while it does show on the script side.
I looked at the Postman request and implemented it in the script, however it still does not work. I tried sending only the file without a json and could not get it working. I've been looking in the documentation of flask and request, but I'm not able to find the explanation why it does not receive the image.
#Script code
import requests
import time
import glob
url = "http://127.0.0.1:5000/transcribe"
for file in glob.glob("/Receipts_to_scan/*.pdf"):
print(open(file, "rb"))
files = {
'file': open(file, 'rb'),
'json': '{"method":"sypht"}'
}
headers = {
'Accept': "application/pdf",
'content-type': "multipart/form-data",
'Connection': 'keep-alive'
}
response_decoded_json = requests.post(url, files=files, headers=headers)
time.sleep(5)
print(response_decoded_json)
#--------------------------
#API code
from flask import Flask, request
#app.route("/transcribe", methods = ["POST"])
def post():
#Getting the JSON data with all the settings in it
json_data = request.files["json"]
print(json_data)
image = request.files["file"]
print(image)
Could you try the following? This way you can combine a file and other data (like a dictionary) in a request.
Change your Flask API:
#Getting the JSON data with all the settings in it
json_data = request.form # <--- change this line
print(json_data)
And then make a request like this (without manually setting the headers):
files = {
'file': (file, open(file, 'rb'), "application/pdf")
}
data = {
"method": "sypht"
}
response_decoded_json = requests.post(url, files=files, data=data)
time.sleep(5)
print(response_decoded_json)
This should give you an ImmutableMultiDict and a FileStorage object to work with.
Your API then prints:
ImmutableMultiDict([('method', 'sypht')])
<FileStorage: 'test.pdf' ('application/pdf')>

urllib2 and json

can anyone point out a tutorial that shows me how to do a POST request using urllib2 with the data being in JSON format?
Messa's answer only works if the server isn't bothering to check the content-type header. You'll need to specify a content-type header if you want it to really work. Here's Messa's answer modified to include a content-type header:
import json
import urllib2
data = json.dumps([1, 2, 3])
req = urllib2.Request(url, data, {'Content-Type': 'application/json'})
f = urllib2.urlopen(req)
response = f.read()
f.close()
Whatever urllib is using to figure out Content-Length seems to get confused by json, so you have to calculate that yourself.
import json
import urllib2
data = json.dumps([1, 2, 3])
clen = len(data)
req = urllib2.Request(url, data, {'Content-Type': 'application/json', 'Content-Length': clen})
f = urllib2.urlopen(req)
response = f.read()
f.close()
Took me for ever to figure this out, so I hope it helps someone else.
Example - sending some data encoded as JSON as a POST data:
import json
import urllib2
data = json.dumps([1, 2, 3])
f = urllib2.urlopen(url, data)
response = f.read()
f.close()
To read json response use json.loads(). Here is the sample.
import json
import urllib
import urllib2
post_params = {
'foo' : bar
}
params = urllib.urlencode(post_params)
response = urllib2.urlopen(url, params)
json_response = json.loads(response.read())
You certainly want to hack the header to have a proper Ajax Request :
headers = {'X_REQUESTED_WITH' :'XMLHttpRequest',
'ACCEPT': 'application/json, text/javascript, */*; q=0.01',}
request = urllib2.Request(path, data, headers)
response = urllib2.urlopen(request).read()
And to json.loads the POST on the server-side.
Edit : By the way, you have to urllib.urlencode(mydata_dict) before sending them. If you don't, the POST won't be what the server expect
This is what worked for me:
import json
import requests
url = 'http://xxx.com'
payload = {'param': '1', 'data': '2', 'field': '4'}
headers = {'content-type': 'application/json'}
r = requests.post(url, data = json.dumps(payload), headers = headers)

Categories