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')>
Related
I have a very basic Flask implementation
When making the request in Postman, I can get the form data but not the file I am trying to upload.
I use the Code Generator in Postman, I copy and paste the code and make the same request using Python Requests, I am able to get both the form data and the file I am uploading.
I have gone through a number of posts about Request.files being empty but nothing that I think helps.
I can upload the same file using the same headers (in Postman), when using another web server.
This is the code I use (generated in Postman):
import requests
url = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
payload={
'Item': 'Test Item',
}
files=[
('filedata',('1.jpg',open('C:/temp/1.jpg','rb'),'image/jpeg'))
]
headers = {
'Authorization': 'Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
}
response = requests.request("POST", url, headers=headers, data=payload, files=files)
print(response.text)
This is the server:
#claim.route('/account/<account>/environment/<env>/attachments', methods=['POST','OPTIONS'])
def upload_attachment(account, env):
try:
Form = []
for form in request.form:
Form.append(form)
Files = []
for uploaded_file in request.files:
file = request.files[uploaded_file]
file_name = file.filename
Files.append(uploaded_file)
Files.append(file_name)
response = {
'Form': Form,
'Files': Files
}
return response
I would like to upload a file from URL using Python requests.post
Would anyone guide me how to convert a file URL into binary data (multipart/form-data) for upload?
I have tried with these code but it return failed.
file = requests.get(file_url, stream=True)
file_upload = {
"name": file_name,
"uploadfile": file.content
}
headers = {
'Content-Type': 'multipart/form-data',
'Accept': 'application/json'
}
requests.post('{POST_URL}', files=file_upload, headers=headers)
POST_URL is external service and only support PDF file (string($binary)).
{
"name": string
"uploadfile": string($binary)
}
Thank you so much.
As per python-requests documentation (Here), if you specify files parameter in requests.post, it will automatically set requests content-type as 'multipart/form-data'. So, you just need to omit the headers part from your post request as:
import requests
file = requests.get('{FILE_URL}', stream=True)
with open({TEMP_FILE}, 'wb') as f:
for chunk in response.iter_content(chunk_size=1024):
if chunk:
f.write(chunk)
binaryContent = open({TEMP_FILE}, 'rb')
a = requests.post('{POST_URL}', data={'key': binaryContent.read()})
Update: You can first try downloading your file locally and posting its binary data to your {POST_URL} service.
Trying to send an image using Requests package to Flask server using forms with post. But the flask server is not able to parse the key image. How to send the image in proper format with requests using forms.
Flask server.py
#app.route('/api/<model_name>/predict/', methods=['POST'])
def predict(model_name):
if "image" in request.files.keys():
return jsonify({"msg": "key found"})
print("image", request.files)
return str(), 200
Requests client.py
def get_predictions(path):
url = "http://localhost:9020/api/fasterrcnn/predict/"
payload = {"image": (path.name, open(path, "rb"), "image/jpeg")}
headers = {'content-type': "multipart/form-data"}
response = requests.post(
url, data=payload, headers=headers, stream=True)
pprint(response.text)
Could someone please tell me the possible cause and solution? If I've missed out anything, over- or under-emphasized a specific point, let me know in the comments.
requests documentation page states that you should use files= parameter for posting multipart files.
Example:
import requests
def get_predictions(path):
url = "http://localhost:9020/api/fasterrcnn/predict/"
files = {"image": (path.name, open(path, "rb"), "image/jpeg")}
response = requests.post(url, files=files)
pprint(response.text)
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()