I have this at django
#csrf_exempt
#require_http_methods(['POST'])
#api_token
def foo(request):
upload_file = request.FILES['file']
random_function(upload_file)
return HttpResponse('done')
and this at another python file
import requests
url = "http://127.0.0.1:8000/api/external/path"
payload = {}
files = {'file': open('csv_file.csv', 'rb')}
headers = {
'x-api-key': 'api-key-token',
'Content-Type': 'application/form-data'
}
response = requests.request("POST", url, headers=headers, data=payload, files=files)
print(response.text.encode('utf8'))
the problem is that when I executed the python file I got this error
django.utils.datastructures.MultiValueDictKeyError: 'file'
it was like request.FILES can't find file name
but when I execute it from postman it works fine
Okay guys, I've tried
headers = {
'x-api-key': 'api-key-token'
}
And then it works. My team said because the boundary has gone missing since we force the content type to be multipart/form-data but I still don't quite get it yet. If anyone can explain it would be much appreciated
Related
I'm currently struggling with a really simple problem, but cant spot the problem in detail.
I want to upload a file via requests.post, the current approach looks kinda like:
fin = open(f"{path_dtl}{filename}.dtl", "rb")
files = {"file": fin}
headers = CaseInsensitiveDict()
headers["Authorization"] = f"Bearer {auth_token}"
headers["Content-Type"] = "application/octet-stream"
headers["Content-Disposition"] = f"form-data;filename ='{filename}.dtl'"
upload_dtl = requests.post(url, headers=headers, files=files)
The result is a {'error': 'Invalid Media Type/Mime Type'} response. Is there a need to open a .dtl file in different manner? The usage of a request with this configuration via Postman works fine so I guess I missed a silly mistake. Thanks in advance.
UPDATE
Alright... for anyone interested. The cause of the issue was the default key-value "file" in files = {"file": fin} is different for my API. Following workaround fixed my issue.
with open(f"{path_dtl}{filename}.dtl", "rb") as f: files = f.read()
...
upload_dtl = requests.post(url, headers=headers, files=files)
Have you tried specifying a type? You can do so like this:
files = {'file': ('aaa.csv', open('aaa.csv', 'rb'),'text/csv')}
POSTMAN i have tried everything to duplicate a POSTMAN POST that is working using Python and i have been unsuccessful. I receive a 500 back and when i print the request I dont see anything wrong. Any suggestions?
```
filename1="untitled.png"
filename="untitled.png"
location = "C:\\myfiles\\"
#files = {"file":(filename1,open(location+'/'+filename,"rb"),'application-type')}
#files = {"file":(filename1,open(location+'/'+filename,"rb"))}
#files = {"file":(filename1, open(location+'/'+filename,'rb'),'application-type')}
files = {'file': (filename1, open(location+'/'+filename,'rb'))}
payload = {'': {
"DateIssued": "2020-02-22T14:35:40.760026-08:00",
"Category":None,
"Title":"Report",
"Title2":"MyReports"
}}
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'PublishService-Api-Key': 'myAPIKey'
}
req = requests.request('POST',"http://myurl.com/PublishService/api/docs/", headers=headers, data=payload, files=files)
print(req)
```
Just remove the Content-Type from header.
headers = {
'PublishService-Api-Key': 'myAPIKey'
}
Explanation here --> How to send a "multipart/form-data" with requests in python?
I am using python to try and get an image from one API, and then post it to a separate API.
So far I have this code:
def create_item(token, user_id):
url = '<api_url_to_post_to>'
headers = {"Authorization": "Token {0}".format(token)}
image_url = '<some_random_image_url>'
image_obj = requests.get(image_url)
data = {
"image": image_obj.content
}
r = requests.post(url, headers=headers, files=data)
response = r.json()
print(response)
return response
The issue is that when I try to post it to the second API, I get a "File extension '' is not allowed." error. This is obviously a custom error message, but it signifies that there is something wrong with the file that I am posting.
Any suggestions on what I may be doing wrong?
Try specifying the file type, just image_obj.content is the raw binary image:
r = requests.post(
url,
headers=headers,
files={'image': ('my_image.jpg', image_obj.content, 'image/jpg')})
This should add the correct headers to the multipart boundary for the image.
If you don't know for sure the content type, you might actually get it from the headers of your previous response: image_obj.headers['Content-Type'] should be "image/jpg" but for a different image it might be "image/png".
It wants a file extension, I'd hazard a guess that image should be image.<SOME_FORMAT>.
I am very new to python (and coding in general) so I hope I articulate my issues well enough. I've managed to cobble together an application that connects to the API of one of my companies software.
I've been able to auth, get the token, pass it to other functions to GET and POST to some API functions. I'm working on a new API call that posts a file. I am STUMPED. All the examples I find show only passing the file but I need to pass the file, and data, and an auth header. I have tried so many variations of my code, and nothing has gotten me any closer.
First, this function is what works, but with a different API (groups) for posting a new group. It doesn't include any files.
def apiPost(token):
if not token == "":
status.run_set_text('Running API POST Call', 3)
headers = { 'Content-Type':'application/json', 'Authorization':'Bearer '+str(token) }
data = {"data":{ 'id':0, 'customerId':33, 'name':'567tuhj', 'description':'sdfgsdfg'}}
r = requests.post(api_url+"v1.1/groups/", headers=headers, data=json.dumps(data))
***other code removed updating status bars***
return r
else:
***other code removed updating status bars***
My dev environment only has access to one customer, but it still requires that I post the customerId to POST.
I've tried hundreds of variations of converting this to posting a file from what I read on the requests site tutorials and some other stackoverflow questions. This posts to the API packageFiles. According to the Swagger page I have access to, it says I need to include the ID and customer ID when uploading the file still.
def apiPost(token):
if not token == "":
status.run_set_text('Running API POST Call', 3)
headers = {'Authorization':'Bearer '+str(token)}
files = {'file': open('log.txt', 'rb')}
data = {"data":{ 'id':0, 'customerId':33}}
r = requests.post(api_url+"v1.1/package_files/"+set_api_pair_value, headers=headers, data=json.dumps(data), file=files)
***other code removed updating status bars***
return r
else:
***other code removed updating status bars***
First, you should format your code to be clean, nice and readable
I am trying to solve your issue, but I think you should attach to your question some kind of expected data, file, request parameters.
def apiPost(token):
if not token == "":
status.run_set_text('Running API POST Call', 3)
headers = { 'Content-Type':'application/json',
'Authorization':'Bearer '+str(token) }
data = {"data":
{ 'id':0,
'customerId':33,
'name':'567tuhj',
'description':'sdfgsdfg'
}
}
#The part you are looking for probably
files = {'name_of_file_field' : open(filename, "rb")}
r = requests.post(api_url+"v1.1/groups/", headers=headers, data=json.dumps(data), files = files)
***other code removed updating status bars***
return r
else:
***other code removed updating status bars***
Comment:I get back a 400 (bad request) with that accepted answer..
{"status":"FAILURE",
"error":[{"code":"5004",
"name":"General Error","severity":"3","message":"Error Occurred During the operation",
"details":{"5004":"General Error null"}}]}
{'Connection': 'keep-alive', 'X-Powered-By': 'Undertow/1', 'Server': 'WildFly/9', 'Content-Length': '172', 'Content-Type': 'application/json;charset=UTF-8', 'X-Application-Context': 'application:9090', 'Date': 'Fri, 28 Sep 2018 17:57:57 GMT'}
Please edit your Question and add your Python and requests Version!
Tried the following, using a Text file instead of Image:
import requests
url = 'http://httpbin.org/anything'
files = {'file': ('helloworld.txt', open('../test/helloworld.txt', 'rb'), 'text/text')}
data = dict(name='barca', country='spain')
r = requests.post(url, files=files, data=data)
# Print my requests.post header, files and data.
r_dict = r.json()
for key in r_dict:
print('{}:{}'.format(key, r_dict[key]))
Response from http://httpbin.org/anything:
<Response [200]>
My requests.post header, files and data, send back from host.
method:POST
files:{'file': 'Hello World'}
url:http://httpbin.org/anything
form:{'name': 'barca', 'country': 'spain'}
origin:xx.xx.xx.xx
args:{}
headers:{'Content-Length': '369',
'Accept': '*/*',
'Content-Type': 'multipart/form-data; boundary=bc3c1927f542430f8166e8f3f27f3c72',
'Host': 'httpbin.org', 'Connection': 'close',
'User-Agent': 'python-requests/2.11.1',
'Accept-Encoding': 'gzip, deflate'}
json:None
data:
Tested with Python:3.4.2 - requests:2.11.1
I'm having problems with a CSV file upload with requests.post method in python 3.
from requests.auth import HTTPBasicAuth
import csv
import requests
user='myuser'
pw='mypass'
advertiserid='10550'
campaignid='12394'
url='http://example.example.com/api/edc/upload/'+advertiserid+'/'+campaignid+'/'+'?encoding=utf-8&fieldsep=%3B&decimalsep=.&date=DD%2FMM%2FYYYY&info=1&process=1'
csv="myfile.csv"
with open(csv, 'r') as f:
r = requests.post(url, files={csv: f})
print(r)
The output is 'Response [502]'
Any idea of what could be the problem?
Many thanks!
You can refer the documentation of Requests library here: post-a-multipart-encoded-file
Change your request line to:
r = requests.post(url, files={'report.csv': f})
Try opening it in binary mode? And with specific 'text/csv' mime type?
with open(csv, 'rb') as f:
r = requests.post(url, files={'file': ('myfile.csv', f, 'text/csv', {'Expires': '0'})})
print(r.text)
If it still does not work, try without the binary, but still with the rest.
If it stiiill does not work, print the exact error message. And 502 (Bad Gateway) might just mean that you're not targetting the right url. (you're not targetting example.com, right?
csv="myfile.csv"
url='http://example.example.com/api/edc/upload/'+advertiserid+'/'+campaignid+'/'+'?encoding=utf-8&fieldsep=%3B&decimalsep=.&date=DD%2FMM%2FYYYY&info=1&process=1'
files = {'upload_file': open(csv,'rb')}
r = requests.post(url, files=files)
Imagine I have a rest API to import the CSV file (Multipart encoded file)
corresponding python request should be like below.
import requests
hierarchy_file_name = '/Users/herle/ws/LookoutLab/data/monitor/Import_Hierarchy_Testcase_v2.csv'
headers = {
'x-api-key': **REST_API_KEY**,
'x-api-token': **REST_API_TOKEN**,
'accept': 'application/json'
}
files = {'file': (hierarchy_file_name, open(hierarchy_file_name, 'rb'), 'text/csv')}
url = "https://abcd.com"
response = requests.post(url +'/api/v2/core/workspaces/import/validate',
files=files, verify=False, headers=headers)
print("Created")
print(response)
print(response.text)
Note:
Make sure that you don't add 'Content-Type': 'multipart/form-data' in the header