POST multipart-form image with python through rest API call - python

I am relatively new to python and enjoying every day I program in it. I have been looking around for a possible solution to figure out how to post an image in a multipart-form, binary format, with a form tag. The API I am trying to call is expecting a binary image in a form.
The request payload sample I have is:
----WebkitFormBoundaryM817iTBsSwXz0iv8
Content-Disposition: form-data, name="image"; filename="123BMW.jpg"
Content-Type: image/jpeg
----WebkitFormBoundaryM817iTBsXwxz0iv8
I have tried several ideas based on some basic requests examples.
Any ideas, thoughts or pointers on where to start looking for such a solution?
def Post_Image(urlPath, filePath, fileName):
url = urlPath headers = {'content-type': 'multipart/form-data'}
files = {'file':(fileName, open(filePath,'rb'))}
payload = {"Content-Disposition": "form-data", "name":fileName}
payload = urllib.urlencode(payload)
resp = requests.post(url, data=payload, headers=headers, files= files)

The problem is you're setting both the data and files parameters, this part of the code sample here:
payload = urllib.urlencode(payload)
resp = requests.post(url, data=payload, headers=headers, files= files)
If both are present, and data value is a string, only it will be in the request. Drop it, and the files will be present.

Related

Zapier - Input data not able to form payload

I've used Zapier quite a bit, but not real familiar with Python. I grabbed the Python Code for creating a room on Daily.co and want to name the room based on data from a form fill to create a video chat link for applicants. I can create a room with a static name, but not sure how to form the payload part of the response with data from Zapier. The Daily.co formatting is not what I have seen in other examples. I added an input_data called roomname, but can't get it into the payload string. I'm including a screen shot and would appreciate some help since I am a novice on Python.
image of Zapier screen
import requests
url = "https://api.daily.co/v1/rooms"
payload = "{"name":"Room1"}"
headers = {
'content-type': "application/json",
'authorization': "Bearer ad95XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX84dd"
}
response = requests.request("POST", url, data=payload, headers=headers)
print(response.text)
I believe you simply need to remove the outer "" from the payload line. Try:
payload = {'name': 'Room1'}

Combining Python Request - files and integer

I am trying to make a request for a form-data type. The request worked previously when it was just two files being used for the request. However, now an ID has to be inputted in the request also, and it won't work.
I have tried lots of different options of trying to get this to work, the ID is an input in a separate file, same as 'file_a' and 'file_b'. However, it is erroring with the ID form data field.
url = url
headers = {"Authorization": Access_token}
files = [('file_a', open(file_a, 'rb')), ('file_b', open(file_b, 'rb')), ('ID', ID)]
response = requests.post(url=url, files=files, headers=headers)
print(response.content)
I am expecting a response json string, however getting no response as the request is not working due to the ID integer field.
From your code sample, it seems ID is a file, but you probably want to pass it as form-encoded data to data argument in requests.post.
To do this create a dictionary containing the name of the field and its value:
url = url
headers = {"Authorization": Access_token}
files = [('file_a', open(file_a, 'rb')), ('file_b', open(file_b, 'rb'))]
data = {'ID', ID} # here's ID value
response = requests.post(url=url, files=files, headers=headers)
print('status code:', response.status_code)
Here you can find the documentation you need to send form data.
Please, let me know whether this helps you or if you need further help.

Python HTTP Post with upload file and headers generated from Postman

I'm using Python 2.7.
I want to make a HTTP POST using requests, where I upload a file and a key that must go in the HTTP Headers.
For that I've used the application Postman, where it works really fine.
On Postman I've added only the necessary header, which is a Authorization with some key.
On the body, Ive choosen form-data and then the key is an input_image, and they the image itself.
Now I want to replicate this into Python2.7, so I've chose to see the Python code on Postman, which was this one:
import requests
url = "https://foo.com/bar/stuff"
payload = "------WebKitFormBoundary7MA4YDxkTrZu1gW\r\nContent-Disposition: form-data; name=\"input_image\"; filename=\"C:\\Test\\projs\\Supermarket\\doritos.jpeg\"\r\nContent-Type: image/jpeg\r\n\r\n\r\n------WebKitFormBoundary7MA4YDxkTrZu1gW--"
headers = {
'content-type': "multipart/form-data; boundary=----WebKitFormBoundary7MA4YDxkTrZu1gW",
'Authorization': "myAuthorizationKey",
'Cache-Control': "no-cache",
'Postman-Token': "0efwd6e8-051c-4ed5-8d6f-7b1bd135f4d5"
}
response = requests.request("POST", url, data=payload, headers=headers)
print(response.text)
This simply doesn't work. It has the same behaviour as if I didn't send any image using Postman. It looks like the payload string is not being send correctly.
Question:
What is wrong with this Postman auto-generation code in order to send a HTTP POST with image upload and with header at the same time in Python?
I think Postman is doing some logic we are not really aware of. But the package requests provide a way to upload images.
files = {'media': open('my_image.jpg', 'rb')}
r = requests.post(url, files=files, headers=hearders)
According to the server you are sending the image to, the parameters name, this code might need to be slightly changed.
the only trick works here is your code should be same as you post request in postman, no extra headers need to be added , your post request should look like the same as it is in postman.
I could do this by changing my file to an image file and then posting it in my post request.
with open('grass-small.png', 'rb') as imageFile:
imageStr = base64.urlsafe_b64encode(imageFile.read())
files = {'document': ('grass-small.png', imageStr ), 'document_type':(None,'grass')}
This worked for me
import requests
url = 'http://iizuka.cs.tsukuba.ac.jp/projects/colorization/web/'
files = {'file': ("my_img_path/myImage.jpeg", open('my_img_path/myImage.jpeg', 'rb'),'image/jpg')}
r = requests.post(url, files=files)

Python mulitpart/formdata POST request within Zapier Code

I'm currently working with Zapier to automate some tasks but I got stuck on the following :
I'm trying to send a POST request using the Zapier Webhooks containing a file. I could make it work trough postman as the API of Debitoor (that's where I am sending to) is pretty clear.
However, I can not make it work within Zapier Webhooks. I also tried to use Zapier Code (Python) as I can view the python code from the postman. But I am not familiar with that and might need some help to get it started.
1.) First of all, this is the API reference: https://developers.debitoor.com/api-reference#files
2.) I then used Postman with this code (Python requests)which was working :
import requests
url = "https://api.debitoor.com/api/files/v1"
querystring = {"token":"eyJ1c2VyIjoiNWE0NmVjYjUxOTE0ODEwMDFjMTkxYzZmIiwiYXBwIjoiNTdiMmZlMDkxZTkwMjQwZjAwNDZhNWEyIiwiY2hhbGxlbmdlIjowLCIkZSI6MCwiJHQiOjE1MjE4NzAwNTQ1OTd9CsKRw5xbw5_DhHUWw5QJw4zDj8KnXsOaeMKA","fileName":"test.pdf"}
payload = "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"file\"; filename=\"Bildschirmfoto 2018-04-05 um 09.59.46 1.png\"\r\nContent-Type: image/png\r\n\r\n\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--"
headers = {
'content-type': "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW",
'cache-control': "no-cache",
'postman-token': "716e7723-2dc1-6384-059d-960feb563443"
}
response = requests.request("POST", url, data=payload, headers=headers, params=querystring)
print(response.text)
3.) Tried to copy the code to Zapier Code, but I don't know how to implement the file. In Zapier I am triggering an inbound email to grab the attachment, which is then "hydrated". It looks like this :
hydrate|||.eJwtjMsOwiAUBf_lrosKNFDZu3Xh1hjC46KklTaFxDRN_11qXJ7JzFkhplxMcqijB8U5l7yT5wZCxMHrZN4Iqo4BMzTgXuh63eMCioruLKiobEwFU9FlmXb1WrX-Y-ZnBrX-Qj2NsSpzBfcV_o-3C2GUisPkwx7sj5D5UQpDmeMnwqW1pPWBE-OYJdYwdCJQT9sWtse2fQEK1Tjl:1eqY0S:s2Ek27XO54PVSm9q_mVMDN8o1uY|||hydrate
How do I connect the Python code to the hydrated file? I have no experience with files and could not find any useful help. Hope someone has an idea?
I was trying to import AWS S3 files to my API.
It turns out that Zapier hydrated my file just as described here.
Then I successfully extracted the content of my file and sent it to my API like this:
import urllib.request
auth_token = input_data['auth_token'] # Authentication token for my API
csv_file = input_data['csv_file'] # The "hydrate|||..." variable: that's my S3 file
file_type = 'text/csv'
fp = urllib.request.urlopen(csv_file)
file_bytes = fp.read() # Binary content of my S3 file
fp.close()
url = 'http://my.api.com/importer/resource'
headers = {
'accept': 'application/vnd.api-v1+json',
'authorization': auth_token,
'user-agent': 'Zapier'
}
files = {'csv_file': ('bulk_resources.csv', file_bytes, file_type, {'Expires': '0'})}
response = requests.post(url, headers=headers, files=files)
return response.json()

How to send file using Request Python with some headers?

I tried to send file with some headers like:
files = {'file': (file, open(file, 'rb'), {'Content-type': 'multipart/form-data; boundary=---BOUNDARY', 'Authorization' : 'Basic ' + api_key})}
r = requests.post(base_url, files=files)
Server returned 401 error that means absent header Authorization. But I sent it
For Basic Authentication you can follow the requests docs. It's visible on the very first line of code in the example on that page.
Use the auth keyword argument to supply a 2-tuple of username and password:
response = requests.post(base_url, files=files, auth=('username', 'password'))
Edit:
If you want to send actual headers, rather than things like Basic Auth, you can do that with the headers keyword argument. This allows you to give a dict of headers you would like to send. For example:
headers = {'Content-Type': 'application/json'}\
response = requests.post(url, data=data, headers=headers)
The auth argument, should be a simplification of the above because Basic Auth is so common, but don't quote me on that one.
You can follow this example to take it from the official documentation I think you should try it first in postman, with the json then and do it from python.
This information is taken from the official documentation
python

Categories