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)
Related
I am attempting to run a POST request in python. When I test in Postman it runs fine and imports the file. When I run it in Python I error out. This posts a spreadsheet stored on my computer into Quip. I am getting the error missing argument 'file'. I have tried moving several things around and am not sure what im missing. here is what im working with:
import requests
url = "https://platform.quip.com/1/threads/import-file"
payload = {'type': 'spreadsheet'}
files = [
('file', open('/Users/admin/Documents/excel/logs/Output/test.xlsx','rb'))
]
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Bearer **************************='
}
response = requests.request("POST", url, headers=headers, data = payload, files = files)
print(response.text.encode('utf8'))
Try to change this line:
files = {'file': open('/Users/admin/Documents/excel/logs/Output/test.xlsx','rb')}
Also I noticed a bug in Postman (version 9.9.1): payload contains only the first field. Be aware of that.
So I would not rely on generated code.
I have a python post request to a server where my flask app is hosted. It works fine and I am able to get the desired data.
But I want to test the API using POSTMAN. I am unable to do that because I am unfamiliar with POSTMAN to some extent.
Below is the python code that I have.
import requests
import ast
import json
resp1 = {}
url = 'http://myflaskapiurl:port/route'
files = {'file': open(r'file that should be uploaded to the server', 'rb')}
r = requests.post(url, files=files, data={"flag":2})
headers = {
'content-type': "multipart/form-data",
'Content-Type': "application/x-www-form-urlencoded",
'cache-control': "no-cache",
}
resp1 = ast.literal_eval(r.text)
print(resp1)
I am struggling with the question whether the data and file that I am trying to post to the server should be in raw json or form-data or x-www-form-urlencoded section of body. Also what should be the actual structure.
Because every time I POST this data using form-data or x-www-form-urlencoded section of body I get the error saying
werkzeug.exceptions.BadRequestKeyError
werkzeug.exceptions.HTTPException.wrap..newcls: 400 Bad Request: KeyError: 'file'
This is how it should look like:
The "params" tab should be empty, maybe you're adding a second file parameter there?
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()
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
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.