-1

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***
Joshua Chmil
  • 1
  • 1
  • 2
  • 3
    Possible duplicate of [unable to post file+data using python-requests](https://stackoverflow.com/questions/33885094/unable-to-post-filedata-using-python-requests) – stovfl Sep 28 '18 at 17:32
  • What else does the swagger doc say about uploading files to the endpoint? Does it make mention what content-type header to be set – Oluwafemi Sule Sep 28 '18 at 17:32
  • @stovfl I am not using curl like that example, I am using requests – Joshua Chmil Sep 28 '18 at 17:39
  • @OluwafemiSule the swagger page shows "Parameter - newPackageFile", "Value - file picker box", Parameter Type - formData" "Data Type - file" – Joshua Chmil Sep 28 '18 at 17:42
  • @stovfl 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'} – Joshua Chmil Sep 28 '18 at 18:11

2 Answers2

1

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***
Community
  • 1
  • 1
Attila Kis
  • 521
  • 2
  • 13
0

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

stovfl
  • 14,998
  • 7
  • 24
  • 51