Post multipart data in python with Requests module - python

I actually want to send mutlipart data on a web-application with python. I'm using this wery useful Requests module (http://requests-fr.readthedocs.org/en/latest/).
I have to send an audio file (stored in local on the system) and 2 parameters (GPS coordonates for information).
I have already mannage to do this with a curl command, but i'm looking for a Requests python implementation.
This is the curl command:
curl -u "user:pass" -F 'audio=#file.wav' -F "latitude=42.44646" -F "longitude=8.46464" 'http://my_server_ip/web/rest/vocal' -v --digest
This is how i'm trying to do that in python Requests:
url = "http://my_server_ip/web/rest/vocal"
files = {'audio' : open('/PATH/record.wav','rb'),'latitude':42.44646,'longitude':8.46464}
r = requests.post(url, auth=HTTPDigestAuth('user','pass'),data=files)
r.json
print r.json
For the moment, the only response i get is a 500 error.
Does someone understand what's wrong ? Feel free to tell me if you see a better solution to do that :)
Greetings!

Solved !
The solution is to separate the files and the datas like that:
files = {'audio' : open('/PATH//record.wav','rb')}
data = {'latitude':latitude,'longitude':longitude}
And build the resquest wit BOTH files AND data parameters:
r=requests.post(url,auth=HTTPDigestAuth('user','pass'),files=files,data=data)

Related

python upload file with curl

i'm trying to upload an apk to server
the code i used to upload using curl is written like this:
curl -u "musername:mypass" -X POST "https://myurl/upload" -F "file=#D:\path\to\location.apk"
i tried to make a script using python with requests library like this:
response = requests.post(
self.urlUpload,
files={"file" : open(self.apkLocation, 'r')},
auth=(self.BSUsername, self.BSToken)
)
but it gives me errors:
{"error":"Malformed archive"}
anyone knows why this erros appeared?
Have you had a chance to try something like below?
import requests
files = {
'file': ('/path/to/app/file/Application-debug.apk', open('/path/to/app/file/Application-debug.apk', 'rb')),
}
response = requests.post('https://api-cloud.browserstack.com/app-automate/upload',
files=files,
auth=('BSUsername ', 'BSToken'))
print (response.text)#THE APP URL (bs://<hashed appid>) RETURNED IN THE RESPONSE OF THIE CALL
Check the BrowserStack REST API doc here

how do i read json data sent with http post in python without any framework?

I am writing small python scripts to send json and receive at other end to understand the working of http post and get. I am able to send the json data but i am not aware how to read that json with python.
Here is my python script which posts json data.
#!/usr/bin/python3
import pycurl
import json
data = {"name":"username", "pass":"userpass", "job": "userjon"}
data = json.dumps(data)
c = pycurl.Curl()
c.setopt(c.URL, 'http://localhost/getRequestData')
c.setopt(c.POSTFIELDS, data)
c.perform()
print("Content-type: text/html")
print()
I will have another script say decodejson.py running on the same server. And i will do rewrite using apache htaccess like,
RewriteEngine On
RewriteBase /
RewriteRule "^getRequestData$" "decodejson.py"
now the redirection is success, how do i decode the json in my decodejson.py script.
i have tried running a php script and decoding it with $_POST variable, it works fine.
<?php
echo json_encode($_POST);
?>
I want to understand how to make it work in python.
I am not using any framework here, as you can see i am enabling cgi method.
Please help me solve this. Thanks!
Use requests library. Its simple and easy to use.
>>> import requests
>>> url = "https://reqres.in/api/users?page=2"
>>> requests.post(url, data={}).text # put your data with data argument
'{"id":"419","createdAt":"2018-11-14T14:18:52.888Z"}'

Spaces in a URL when using requests and python

I hope I can explain myself. with out making an arse of myself.
I am trying to use python 3.4 to send a url to a sparkcore api.
I have managed to use curl direcly from the windows command line:-
curl https://api.spark.io/v1/devices/xxxxxxxxxxxxxxx/led -d access_token=yyyyyyyyyyyyyyyy -d params=l1,HIGH
All works fine. there is a space between the led and -d, but that is not a problem.
I have read that reting to do this within python using libcurl is a big pain and I saw lots of messaged about using Requests, so I though I would give it a go.
So I wrote a small routine:
import requests
r = requests.get('https://api.spark.io/v1/devices/xxxxxxxxxxxxxxxxxx/led -d access_token=yyyyyyyyyyyyyyyyy -d params=l1,HIGH')
print(r.url)
print(r)
I get as return:
<Response [400]>
When I examine the URL which actually got sent out the spaces in the URL are replaced with %20. This seems to be my actual problem, because the %20 being added by requests are confusing the server which fails
"code": 400,
"error": "invalid_request",
"error_description": "The access token was not found"
I have tried reading up on how to inpractice have the spaces with out having a %20 being added by the encoding, but I really could do with a pointer in the right direction.
Thanks
Liam
URLs cannot have spaces. The curl command you are using is actually making a request to the url https://api.spark.io/v1/devices/xxxxxxxxxxxxxxx/led with some command line arguments (using -d)
The curl man (manual) page says this about the -d command line argument
-d, --data
(HTTP) Sends the specified data in a POST request to the HTTP server, in the same way that a browser does when a user has filled in an HTML form and presses the submit button. This will cause curl to pass the data to the server using the content-type application/x-www-form-urlencoded. Compare to -F, --form.
-d, --data is the same as --data-ascii. To post data purely binary, you should instead use the --data-binary option. To URL-encode the value of a form field you may use --data-urlencode.
If any of these options is used more than once on the same command line, the data pieces specified will be merged together with a separating &-symbol. Thus, using '-d name=daniel -d skill=lousy' would generate a post chunk that looks like 'name=daniel&skill=lousy'.
If you start the data with the letter #, the rest should be a file name to read the data from, or - if you want curl to read the data from stdin. Multiple files can also be specified. Posting data from a file named 'foobar' would thus be done with --data #foobar. When --data is told to read from a file like that, carriage returns and newlines will be stripped out.
So that says -d is for sending data to the URL with the POST request using the content-type application/x-www-form-urlencoded
The requests documentation has a good example of how to do that using the requests library: http://docs.python-requests.org/en/latest/user/quickstart/#more-complicated-post-requests
So for your curl command, I think this should work
import requests
payload = {'access_token': 'yyyyyyyyyyyyyyyy', 'params': 'l1,HIGH'}
r = requests.post("https://api.spark.io/v1/devices/xxxxxxxxxxxxxxx/led", data=payload)
print(r.text)

Python Requests Put not working with build.phonegap.com

I am making a python build script for a phonegap project.
I need to open the ios key before i build
I am trying to do this with a http put request through the requests module for python.
If i do it with cURL from command line, it works fine
curl -vvv -d 'data={"password":"myPassWord"}' -X PUT https://build.phonegap.com/api/v1/keys/ios/193686?auth_token=passwordlesstokenphg
But from python like this.
password_for_key = {'password': 'myPassword'}
authentication_token = {'auth_token': 'passwordlesstokenphg'}
requests.put('https://build.phonegap.com/api/v1/keys/ios/193686', data=password_for_key, params=authentication_token)
It just returns the json you would recieve if you did a cURL without the data.
For me it seems like the data is not being sent to phonegap correctly.
API reference from build.phonegap.com
docs.build.phonegap.com/en_US/2.9.0/developer_api_write.md.html
Please help :)
So when you do
curl -d "..." -X PUT https://example.com
curl sends exactly what's in that string. requests does not translate so directly to curl. To do something similar in requests you need to do the following:
import json
password_for_key = {'password': 'myPassword'}
authentication_token = {'auth_token': 'passwordlesstokenphg'}
requests.put('https://build.phonegap.com/api/v1/keys/ios/193686',
data={'data': json.dumps(password_for_key)},
params=authentication_token)
What requests will do is build data={"password":"myPassword"} for you if you use the above. First you have to JSON encode the data in password_for_key then pass it in the dictionary to data.

pycurl only geting part of the response

I'm making a request in python using pycurl to a URL which returns a reasonably large json formatted response. When I goto the URL in a browser I see the entire contents, but if I use pycurl and print the received data, I only see about half of what I see when I browse to the URL, and I get an error parsing the data using the json library stating :
ValueError: Unterminated string starting at: line 1 column 16078 (char 16078)
The pycurl request is this :
conn = pycurl.Curl()
conn.setopt(pycurl.URL, myUrl)
conn.setopt(pycurl.WRITEFUNCTION, on_receive)
conn.setopt(pycurl.CONNECTTIMEOUT, 30)
conn.setopt(pycurl.TIMEOUT, 30)
conn.setopt(pycurl.NOSIGNAL, 10)
conn.perform()
with the on_receive function currently just printing the data.
Does anybody know why I am only getting part of the response? I have used massive timeouts just for trying to solve this, I had initially not specified any timeouts but was still getting this error.
in pycurl, you could set this,
import pycurl
pycurl.CONTENT_LENGTH_DOWNLOAD
try using
import Curl, pycurl
con = Curl()
con.set_option(pycurl.CONTENT_LENGTH_DOWNLOAD, 9999999999)
con.get('url' ....
also try following until it works:
pycurl.SIZE_DOWNLOAD
pycurl.REQUEST_SIZE
You could try to access those json data with curl tool.
When you're able to get data, just translate curl options to pycurl options.
curl --help | less

Categories