I'm having a zip file that needs to be uploaded. When I use the CURL command, it is uploading it but when I try the same using Python Requests, i get HTTP 405 Method Not Allowed.
The zip file is usually around 500kb.
Curl command -
curl -u<username>:<password> -T /log/system/check/index.zip "<target URL>"
Python Script (tried 2 different ways) -
1:
import requests
files = {'file': open('/log/system/check/index.zip', 'rb')}
r = requests.post(url, files=files, auth=('<username>', '<password>'))
2:
import requests
fileobj = open('/log/system/check/index.zip', 'rb')
r = requests.post(url, auth=('<username>', '<password>'), files={"archive": ("index.zip", fileobj)})
Am I missing something obvious?
may be this will help you.
with open(zipname, 'rb') as f:
uploadbase = requests.put('url',
auth=(base, pwd),
data=f,
headers={'X-File-Name' : zipname,
'Content-Disposition': 'form-data; name="{0}"; filename="{0}"'.format(zipname),
'content-type': 'multipart/form-data'})
the difference between put and post
curl -T ... uses PUT method instead of POST.
As the error message says, you should use
r = requests.put(url, ...)
Related
Can you please help me convert the following CURL command into a command for Python's requests library?
curl -F pdb_file[pathvar]=#/path/myfile.pdb -X POST https://proteins.plus/api/pdb_files_rest -H "Accept: application/json"
I've tried many things, like this:
import requests
file = open("3w32.pdb", "rb")
url = "https://proteins.plus/api/pdb_files_rest"
response = requests.post(url, data=file)
response.json()
or this:
import requests
file = open("3w32.pdb", "rb")
url = "https://proteins.plus/api/pdb_files_rest"
response = requests.post(url, data={"pdb_file[pathvar]": file}, json={"Accept": "application/json"})
response.json()
but I can't make it work. I either get an error from the server, or a JSONDecodeError in Python.
Try this answer https://stackoverflow.com/a/22567429/4252013
Instead of using "data" argument try with "file"
Ok, I managed to solve it at last.
The problem was that the 'pdb_file[pathvar]' part in the curl command should've been added to the request, like this:
import requests
file = open("3w32.pdb", "rb")
url = "https://proteins.plus/api/pdb_files_rest"
response = requests.post(url, files={'pdb_file[pathvar]':file})
response.json()
Now it works!
The problem in your code is that you have only opened the file and passed the pointer. you can pass the file contents by having file.read() in place.
Please refer this block of code:
import requests
file = open("3w32.pdb", "rb")
url = "https://proteins.plus/api/pdb_files_rest"
response = requests.post(url, data=file.read())
response.json()
I am trying to send a turtle file via a Python script using REST api to the local repository but the System is returning the following error
MALFORMED DATA: Illegal subject value: "-"^^http://www.w3.org/2001/XMLSchema#integer [line 1]
400
The used code is as follows:
import requests
url = 'http://localhost:7200/repositories/metaphactory1/statements'
with open("graph-29.ttl", "rb") as ttl_file:
file_dict = {"graph-29.ttl" : ttl_file}
headers = {
"Content-type": "application/x-turtle;charset=UTF-8",
}
r = requests.post(url, files=file_dict, headers=headers)
print(r.text)
print(r.status_code)
The same file when tried with a Curl command is working fine:
curl -X POST -H "Content-Type: application/x-turtle" -T graph-29.ttl 'http://localhost:7200/repositories/metaphactory1/statements'
Any idea regarding this issue is welcome
I think your problem come from the way you pass your file to the post request.
You should try using the data parameter of the post request. For example:
import requests
url = 'http://localhost:7200/repositories/metaphactory1/statements'
file_path = '/path/to/your/file/graph-29.ttl'
graph_name = 'http://graph-29'
headers = {
'Content-type': 'application/x-turtle',
}
params = {'graph': graph_name} #optional
response = requests.post(url, headers=headers, params=params, data=open(file_path,'r', encoding='utf-8').read())
I am trying to translate a specific curl method into Python's requests module to upload a file to to an api. My standard method that works for non-file requests looks like this:
import requests
requestObject = requests.Session()
standard_headers = {header1:headerValue1,header2:headerValue2}
payload = {key1:value1,key2:value2}
url = 'https://myUrl.com/apiCall'
requestObject.post(url,headers=standard_headers, json=payload)
This works for non-file requests that I need to make to the API. However for file uploads, the API documentation shows a method using curl:
curl -XPOST -H 'header1' -H 'header2 'https://myUrl.com/apiCall' \
-F 'attachment=#/path/to/my/file' \
-F '_json=<-;type=application/json' << _EOF_
{
"key1":"keyValue1",
"key2":"keyValue2"
}
_EOF_
I tested the curl command and it works successfully.
My question is how do I translate that curl method using the << _EOF_ method in Python requests. One idea I had was simply to use the 'files' option in the requests module:
requestObject = requests.Session()
standard_headers = {header1:headerValue1,header2:headerValue2}
payload = {key1:keyValue1,key2:keyValue2}
url = 'https://myUrl.com/apiCall'
file_to_upload = {'filename': open('/path/to/my/file', 'rb')}
requestObject.post(url,headers=standard_headers, files=file_to_upload, json=payload)
But that does not seem to work as the necessary json parameters (the values in payload) do not appear to get passed to the file upload
I also tried specifying the json parameters directly into the file_to_upload variable:
requestObject = requests.Session()
standard_headers = {header1:headerValue1,header2:headerValue2}
url = 'https://myUrl.com/apiCall'
file_to_upload = {'attachment': open('/path/to/my/file', 'rb'),'{"key1":"keyValue1","key2":"keyValue2"}'}
requestObject.post(url,headers=standard_headers, files=file_to_upload)
Similar result, it seems as though I am not passing the necessary json values correctly. I tried a few other ways but I am overlooking something. Any insight into how I should structure my request is appreciated.
Ok I managed to get it to work and posting for anyone who might need help in the future.
The trick was to include the _json key in the data field. My code ended up looking like so:
import requests
requestObject = requests.Session()
standard_headers = {header1:headerValue1,header2:headerValue2}
json_fields = json.dumps({
"key1": "key1Value",
"key2": "key2Value"
})
payload = {"_json":json_fields)
file = {"attachment": /path/to/my/file}
url = 'https://myUrl.com/apiCall'
requestObject.post(url,headers=standard_headers, files=file, data=payload)
Hope that helps some future person.
I can't seem to convert cURL to python. From the docs:
curl -i --upload-file ~/Desktop/Myimage.jpg -H 'Authorization: Bearer Redacted' "https://api.linkedin.com/mediaUpload/C5522AQHn46pwH96hxQ/feedshare-uploadedImage/0?ca=vector_feedshare&cn=uploads&m=AQLKRJOn_yNw6wAAAW2T0DWnRStny4dzsNVJjlF3aN4-H3ZR9Div77kKoQ&app=1983914&sync=0&v=beta&ut=1Dnjy796bpjEY1
I have tried using files instead of data to no avail.
The current code below creates the proper response 201, but it's blank (has no JSON details with an image to use for future API calls). Let me what changes I need to make to upload a file via a PUT request without using a multi-part form (ie "files=")
uploadUrl = data["value"]["uploadMechanism"]["com.linkedin.digitalmedia.uploading.MediaUploadHttpRequest"]["uploadUrl"]
filename = "ffadfads.jpeg"
media_url = "https://1000logos.net/wp-content/uploads/2017/03/LinkedIn-Logo.png"
request = requests.get(media_url, stream=True)
if request.status_code == 200:
with open(filename, 'wb') as image:
for chunk in request:
image.write(chunk)
#files = {'fileupload': open(filename)}
files = {"fileupload":(filename,open(filename,"rb"),'application-type')}
image_headers = {
'Accept': 'image/jpeg,image/png,image/gif',
'Authorization': 'Bearer ' + real_token
}
response = requests.request("PUT", uploadUrl, data=open(filename,"rb"), headers=image_headers)
print response
print response.text
print response.json()
Try not to confuse a request with a response.
response1 = requests.get(media_url, stream=True)
if response1.status_code == 200:
response2 = requests.request("PUT", uploadUrl,
data=response1.iter_content(),
headers=image_headers)
If you are not bound to use the requests library, you could try running the curl command directly from python, using subprocess.run() and shlex.split() for Python 3.
Using the example curl command from your question (adding a missing double quote at the end) the following code would run it and capture the response as text.
import shlex
import subprocess
curl_command_line = '''curl -i --upload-file ~/Desktop/Myimage.jpg \
-H 'Authorization: Bearer Redacted' \
"https://api.linkedin.com/mediaUpload/C5522AQHn46pwH96hxQ/feedshare-uploadedImage/0?ca=vector_feedshare&cn=uploads&m=AQLKRJOn_yNw6wAAAW2T0DWnRStny4dzsNVJjlF3aN4-H3ZR9Div77kKoQ&app=1983914&sync=0&v=beta&ut=1Dnjy796bpjEY1"'''
args = shlex.split(curl_command_line)
response = subprocess.run(args, capture_output=True, text=True).stdout
For Python 2.7, replace the last line with:
response = subprocess.call(args)
I have an application I wrote that downloads a file from a database service I use and then I convert the file to another format and re-upload. The issue is with the upload. I am using a patch request and it completes without errors but the file is never actually uploaded.
Here is my code:
for person in r['records']:
try:
# Get Voicemail and handle conversion if necessary
vm = person['fields']['Voicemail'][0]['url']
if '.m4a' in vm:
vm_name = person['fields']['Voicemail'][0]['filename'].replace('.m4a', '').replace(' ', '')
# Download file to local machine and convert to .mp3
r = requests.get(vm, allow_redirects=True)
open('{}.m4a'.format(vm_name), 'wb').write(r.content)
bash = 'ffmpeg {0}.mp3 -i {0}.m4a -codec:a libmp3lame -qscale:a 1'.format(vm_name)
os.system(bash)
s = requests.Session()
s.mount('file://', FileAdapter())
cwd = os.getcwd()
# url = s.get('file:///{}/{}.mp3'.format(cwd, vm_name))
# Upload/delete files to server
r = requests.patch('https://api.airtable.com/v0/{}/People/{}'.format(base_id, person['id']),
json={"fields": {"Voicemail": [{"url": 'file:///{}/{}.mp3'.format(cwd, vm_name)}]}},
headers={"Authorization": "Bearer {}".format(at_auth), "Content-type": "application/Json"})
print(r.text)
# Delete temporary local files
os.remove('{}.mp3'.format(vm_name))
os.remove('{}.m4a'.format(vm_name))
...And the response of r.text:
{"id":"recnlJBNEWFMLwYNh","fields":{"Name":"Matthew Sewell","Phone":["reciInRjmNpyTabUS"],"Voicemail":[{"id":"att7YiG4s0Epa3V6o","url":"file:////Users/test/Dropbox/python/projects/business/testing123.mp3","filename":"testing123.mp3"}]},"createdTime":"2018-08-09T00:59:35.000Z"}
I am not super familiar with patch requests so any help is appreciated.
Shamelessly copy pasted from another answer (i flagged the question). This is how you can upload data using requests. It doesnt matter if you use GET, POST, PATCH or whatever:
If upload_file is meant to be the file, use:
files = {'upload_file': open('file.txt','rb')}
values = {'DB': 'photcat', 'OUT': 'csv', 'SHORT': 'short'}
r = requests.post(url, files=files, data=values)
and requests will send a multi-part form POST body with the upload_file field set to the contents of the file.txt file.
The original so post is here