Python and pushbullet api: send a file - python

I'm trying to send a file using Pushbullet following their API docs.
This is my function:
def push_file(AccessToken, file_name):
f = open(file_name, 'rb')
file_type = mimetypes.guess_type(file_name)[0]
print("Uploading {0}...".format(file_name))
try:
data = {
'file_name': file_name,
'file_type' : file_type
}
resp = requests.post(UPLOAD_REQUEST_URL, data=data, auth=(AccessToken, '')).json()
if resp.get('error') != None:
print("Error: {0}".format(resp.get('error')['message']))
return
file_url = resp.get('file_url')
print(file_url)
resp = requests.post(resp.get('upload_url'), data=resp.get('data'), auth=(AccessToken, ''), files={'file': f})
data = {
'type' : 'file',
'file_name' : file_name,
'file_type' : file_type,
'file_url' : file_url,
'body' : ''
}
resp = requests.post(PUSH_URL, data=data, auth=(AccessToken, '')).json()
except requests.exceptions.ConnectionError:
traceback.print_exc()
f.close()
But I keep getting:
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='s3.amazonaws.com', port=443): Max retries exceeded with url: /pushbullet-uploads (Caused by <class 'ConnectionResetError'>: [Errno 104] Connection reset by peer)
If I use another AccessToken I still get this error, even if it's the first time I post to that url.

The upload process is unfortunately not very good and will hopefully be improved soon. It is the one request that does not obey the JSON rule. There is a curl example that shows this (https://docs.pushbullet.com/#upload-request), but understanding curl syntax is basically impossible.
Here's an example that I just typed up and seems to work:
import requests
import json
ACCESS_TOKEN = '<your access token here>'
resp = requests.post('https://api.pushbullet.com/v2/upload-request', data=json.dumps({'file_name': 'image.jpg'}), headers={'Authorization': 'Bearer ' + ACCESS_TOKEN, 'Content-Type': 'application/json'})
if resp.status_code != 200:
raise Exception('failed to request upload')
r = resp.json()
resp = requests.post(r['upload_url'], data=r['data'], files={'file': open('image.jpg', 'rb')})
if resp.status_code != 204:
raise Exception('failed to upload file')
print r['file_name'], r['file_type'], r['file_url']

According to the Pusbullet API
All POST requests should be over HTTPS and use a JSON body with the
Content-Type header set to "application/json".
Try changing your requests.post calls like so:
resp = requests.post(UPLOAD_REQUEST_URL, json=data, auth=(AccessToken, '')).json()
Use json=data instead of data=data. Requests will automatically set Content-Type to application/json.

Related

How to solve "[Winerror]:10054 An existing connection was forcibly closed by the remote host"?

I am trying to fetch the json response using the VirusTotal API. To fetch the results as a response I have created a python script which is as shown below : Then error show like this : [Winerror]:10054 An existing connection was forcibly closed by the remote host
import requests
url = "https://www.virustotal.com/vtapi/v2/file/scan"
api_key = "MyApiKey"
params = {"apikey": api_key}
files = {"file": ("app.exe", open("C:/Users/Administrator/Desktop/malware detection/app.exe", "rb")}
try:
response = requests.post(url, files=files, params=params)
print(response.json())
except Exception as e:
print(e)
To provide more information, please try the following:
import requests
url = "https://www.virustotal.com/vtapi/v2/file/scan"
api_key = "MyApiKey"
params = {"apikey": api_key}
files = {"file": ("app.exe", open("C:/Users/Administrator/Desktop/malware detection/app.exe", "rb"))}
try:
response = requests.post(url, files=files, params=params)
print(response.json())
except Exception as e:
print(e)
And post the error response you receive from the updated code.
This issue is resolved, The issue was encountered only for the skype.exe file. while scanning using malware machine learning.

how to print request body in urllib3 python

I can successfully make a post multipart request using urllib3 library in python. However how to print the request body when POST request was made?
In python requests library: we have the option like: print(response.request.body)
code looks like this:
http = urllib3.PoolManager()
path_bdl = os.path.dirname(__file__) + '/some_bin_file.xyz'
content_json = os.path.dirname(__file__) + '/some_json.json'
with open(path_, 'rb') as fp:
binary_data = fp.read()
with open(content_json, 'r') as j:
json_data1 = j.read()
url = "//myurl"
headers = {} # dictionary
response = http.request(
'POST',
url,
fields={
"abc": (content_json, json_data1, "application/json"),
"bbb": (path_, binary_data, "xyz_Content_type")
},
headers=headers
)
print('\n StatusCode: ', response.status)
print(response.headers)
print(response.request) >>>>>>>>>>>> HTTPResponse has no attribute 'request'
From the docs:
The HTTPResponse object provides status, data, and headers attributes
Try using response.data for reading the data part of the response.

Upload data as image to Wordpress using Wordpress API

I am trying to take the URL of an image, download it, and then upload it to wordpress using the Wordpress API. Here is my code:
def upload_media(self, media_url):
# Get the last path component
filename = media_url.split('/')[-1]
response = requests.get(media_url)
if response.status_code == 200:
image = Image.open(BytesIO(response.content))
upload_url = self.__upload_media_url()
headers = { "Content-Disposition": f'attachment; filename={filename}'}
files = { 'file': image.tobytes() }
request = requests.post(upload_url, auth=(self.username, self.password), files=files, headers=headers)
return request
Each time this fails with the following error:
{'code': 'rest_upload_unknown_error', 'message': 'Sorry, this file type is not permitted for security reasons.', 'data': {'status': 500}}
Originally I had the following code, which worked on my local machine. However, because I want to run this on Google Cloud Functions, I do not have access to the file system. Thus the process of open/close will not work.
def upload_media(self, media_url):
# Get the last path component
filename = media_url.split('/')[-1]
response = requests.get(media_url)
if response.status_code == 200:
with open(filename, 'wb') as file:
file.write(response.content)
upload_url = self.__upload_media_url()
headers = { "Content-Disposition": f'attachment; filename={filename}'}
files = { 'file': open(filename, 'rb')}
request = requests.post(upload_url, auth=(self.username, self.password), files=files, headers=headers)
os.remove(filename)
return request
Is there a way to do this?
According to https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.tobytes image.tobytes() produces RAW image data, not PNG or JPG compressed data - so, what you're trying to upload is not one of the allowed types.
Just drop this line:
image = Image.open(BytesIO(response.content))
and then use:
files = { 'file': BytesIO(response.content) }
I believe this should fix your problem.
Ultimately I had to make 2 changes to my original function.
Add a Content-type: image/jpeg
Use data= instead of file=
Here is the working function which requires no open/closing of any files:
def upload_media(self, media_url):
# Get the last path component
filename = media_url.split('/')[-1]
response = requests.get(media_url)
if response.status_code == 200:
upload_url = self.__upload_media_url()
headers = { "Content-Disposition": f"attachment; filename={filename}" , "Content-Type": "image/jpeg" }
return requests.post(upload_url, auth=(self.username, self.password), headers=headers, data=response.content)

Uploading a file to a Django PUT handler using the requests library

I have a REST PUT request to upload a file using the Django REST framework. Whenever I am uploading a file using the Postman REST client it works fine:
But when I try to do this with my code:
import requests
API_URL = "http://123.316.118.92:8888/api/"
API_TOKEN = "1682b28041de357d81ea81db6a228c823ad52967"
URL = API_URL + 'configuration/configlet/31'
#files = {
files = {'file': open('configlet.txt','rb')}
print URL
print "Update Url ==-------------------"
headers = {'Content-Type' : 'text/plain','Authorization':API_TOKEN}
resp = requests.put(URL,files=files,headers = headers)
print resp.text
print resp.status_code
I am getting an error on the server side:
MultiValueDictKeyError at /api/configuration/31/
"'file'"
I am passing file as key but still getting above error please do let me know what might I am doing wrong here.
This is how my Django server view looks
def put(self, request,id,format=None):
configlet = self.get_object(id)
configlet.config_path.delete(save=False)
file_obj = request.FILES['file']
configlet.config_path = file_obj
file_content = file_obj.read()
params = parse_file(file_content)
configlet.parameters = json.dumps(params)
logger.debug("File content: "+str(file_content))
configlet.save()
For this to work you need to send a multipart/form-data body. You should not be setting the content-type of the whole request to text/plain here; set only the mime-type of the one part:
files = {'file': ('configlet.txt', open('configlet.txt','rb'), 'text/plain')}
headers = {'Authorization': API_TOKEN}
resp = requests.put(URL, files=files, headers=headers)
This leaves setting the Content-Type header for the request as a whole to the library, and using files sets that to multipart/form-data for you.

HTTP POST using urllib2

IN the code below, I am trying to make a POST of data with urllib2. However, I am getting a HTTP 400 bad request error. Can anyone help me with why this might be the case? The URL is reachable from my computer and all relevant ports are open.
data = {'operation' : 'all'}
results = an.post(an.get_cookie(), 'http://{}:8080/api/v1/data/controller/core/action/switch/update-host-stats'.format(an.TARGET), data)
print results
def post(session_cookie, url, payload):
data = urllib.urlencode(payload)
req = urllib2.Request(url, data)
req.add_header('Cookie','session_cookie=' + session_cookie)
try:
returnedData = urllib2.urlopen(req, data, timeout = 30)
data = json.load(returnedData)
except urllib2.URLError, e:
print e.code
print 'URL ERROR'
return {}
return data
The following code works for me:
import json
import urllib2
import logging
def post_json_request(url, post_data, optional_headers = {}):
"""
HTTP POST to server with json as parameter
#param url: url to post the data to
#param post_data: JSON formatted data
#return: response as raw data
"""
response = ""
try:
req = urllib2.Request(url, post_data, optional_headers)
jsonDump = json.dumps(post_data)
response = urllib2.urlopen(req, jsonDump)
except Exception, e:
logging.fatal("Exception while trying to post data to server - %s", e)
return response
I'm using it in various stubborn platforms that insist to retrieve data on a specific method.
Hope it will help,
Liron

Categories