I'm trying to upload a picture with the python sdk:
Code:
graph = facebook.GraphAPI(self.current_user.access_token)
graph.put_object("me", "photos", name = "test", message = raw_picture_data)
But I get the error "GraphAPIError: (#324) Requires upload file". I don't think its a permissions issue as I've requested perms="user_photos,friends_photos,publish_stream". Does anyone know what this error means and how to resolve it?
I used this library to encode the image: http://atlee.ca/software/poster/
Add this to facebook.py:
from poster.encode import *
from poster.streaminghttp import register_openers
def put_photo(self, source, album_id=None, message=""):
object_id = album_id or "me"
register_openers()
content_type,body = multipart_encode( [ ('message',message),('access_token',self.access_token),('source',source) ] )
req = urllib2.Request("https://graph.facebook.com/%s/photos" % object_id, content_type,body )
try:
data = urllib2.urlopen(req).read()
except urllib2.HTTPError as e:
data = e.read()
try:
response = _parse_json(data)
if response.get("error"):
raise GraphAPIError(response["error"].get("code", 1),response["error"]["message"])
except ValueError:
response = data
return response
Call the function with the photo as a file like object:
graph = facebook.GraphAPI(access_token)
photo = open("myphoto.bmp","rb")
graph.put_photo(photo,"me","This is my brilliant photo")
The put_photo method has been submitted by someone (I forget who) as proposed a function to add to the API but it didn't work for me till I used poster to encode the image.
Hope this helps.
Just battled with a similar error a bit. I did not use the SDK but just a POST to the graphapi. For me, this error happened when i didnt supply a filename to the file upload field in the "form" sent to facebook.
This is my code (poster - http://pypi.python.org/pypi/poster/0.8.1)
from poster.encode import multipart_encode, MultipartParam
url = 'https://graph.facebook.com/me/photos?access_token=%s'%model.facebook_token
file_param = MultipartParam(name = 'source',
filename = 'photo.jpg', #this is crucial!!!
fileobj = blob_reader) #the blob reader is the fileobject for the file (with read() method)
message_param = MultipartParam(name = 'message',
value = 'test message')
datagen, headers = multipart_encode([file_param,
message_param])
from google.appengine.api import urlfetch
result = urlfetch.fetch(url,
payload = ''.join(datagen),
headers = headers,
method = 'POST')
return result.content
Related
I am trying to use FileResponse.set_header() to set Content-Disposition to attachment, so that Audio file can be downloaded rather than playing on the browser, in my python/django powered website.
is there any way i can implement this code bellow to make it work?
song = models.song.objects.filter(id__exact=song_id).first()
file_name = ntpath.basename(song.songfile.url)
content_type = 'audio/mpeg'
with open(identify_song.songfile.path, 'rb') as my_f:
file_like = my_f
response = FileResponse(my_f, content_type=content_type, as_attachment=True, filename="{}".format(file_name))
response['Content-Disposition'] = 'attachment; filename="{}"'.format(file_name)
size = response['Content-Length'] = os.path.getsize(identify_song.songfile.path)
#print(file_name)
return(response)
this code does not give me any error but it's not working.
So i discovered about FileResponse.set_header() in the django doc, so i tried using it like so.
`song = models.song.objects.filter(id__exact=song_id).first()
file_name = ntpath.basename(song.songfile.url)
FileResponse.set_headers(file_name, filelike='audio/mpeg', as_attachment=True)`
Then i got an error AttributeError: 'str' object has no attribute 'filename'.
please can anyone help me out, or if there is another way to do that in django i will so much appreciate someone's help. Or any other possible way i can set my Content-Disposition, in django, Nginx or in Javascript.
I have been working all day with this functionality in order to download a generated file, lemme share you how I did it, it worked like a charm.
documentation : https://docs.djangoproject.com/en/3.0/ref/request-response/
http header 'Content-Disposition': https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition
try:
wdata = request.GET
download = wdata.get("download") or ''
allowed_params = [
'template', 'bases',
]
if download in allowed_params:
out, err = utldol.download_file(download, request)
if err:
raise ValueError(str(err))
else:
raise ValueError(str('Parameter not recognized'))
file = FileResponse(
out.get("file"), filename=out.get("filename"),
)
file['Content-Disposition'] = 'attachment; filename="{}"'.format(
out.get("filename")
)
return file
except Exception as ex:
return HttpResponseBadRequest(str(ex))
The parameter "file" contains the file instance : open('file.txt','rb') :
out.get("file")
The parameter "filename" contains the name of the file
out.get("filename")
finally, when the file is throw by the browser :
Hope my experience would be helpful, any views, please just lemme know.
greetings,
There is no answer to this question as the method 'FileResponse.set_header()' can be called with a file like object only and it makes some guesses about the header which are not reliable if you use file types that are rather exotic. At least you can overwrite this function that returns nothing but only sets the header information or you can do this little task in your code yourself. Here is my example using an in-memory string buffer.
filename = "sample.creole"
str_stream = StringIO()
str_stream.write("= Some Creole-formated text\nThis is creole content.")
str_stream.seek(0)
response = FileResponse(str_stream.read())
response.headers['Content-Disposition'] = 'attachment; filename={}'.format(filename)
response.headers['Content-Type'] = 'application/creole'
return response
With that approach yo can still use the default 'FileResponse.set_header()' functionality to set the 'Content-Length' which works properly. As the other 'FileResponse' parameters such as 'as_attachment' and 'filename' don't work as reliable. Probably nobody noticed yet as 'FileResponse' is rarely used, and as a matter of fact the same functionality can be implemented using 'HttpResponse'.
response = HttpResponse(content_type='application/creole')
response.headers['Content-Disposition'] = 'attachment; filename={}'.format(filename)
response.write(str_stream.read())
return response
The utldol it is a python file that contains a function, that generates a xls file. The function returns smth like these :
outcome, error = None, None
try:
........
........
file = open(output.get("filedir"), 'rb')
outcome = {
"file": file, "filename": output.get("filename"),
}
except Exception as ex:
error = str(ex)
return [outcome, error]
output contains the fullpath of the xls file generated then it is read by "open" function.
I am trying to pass "pdf" or "html" file directly into lambda function. But I dont understand the correct format in which it should be received?
Eg: I was able to under stand how to pass "image" files through lambda functions by using the following code: But how do I send a pdf or html file?
def write_to_file(save_path, data):
with open(save_path, "wb") as f:
f.write(base64.b64decode(data))
def ocr(img):
ocr_text = pytesseract.image_to_string(img, config = "eng")
return ocr_text
def lambda_handler(event, context=None):
write_to_file("/tmp/photo.jpg", event["body"])
im = Image.open("/tmp/photo.jpg")
try:
ocr_text = ocr(im)
except Exception as e:
print(e)
# Return the result data in json format
return {
"statusCode": 200,
"body": ocr_text
}
Edit: I am trying to pass the "pdf" or "html" directly through API gateway (binary) and not through S3.
You can use the API gateway Content type conversions.
You can refer to this documentation
Thanks. But after massive online searching and try/repeat, was able to find the answer for html file. Similar thing should work for pdf also.
import json
import bs4
from bs4 import BeautifulSoup
from bs4.element import Comment
import base64
def tag_visible(element):
if element.parent.name in ['style', 'script', 'head', 'title', 'meta','table', '[document]']:
return False
if isinstance(element, Comment):
return False
return True
def lambda_handler(event, context):
# This will work for testing purpose only
#soup = BeautifulSoup(event["body"], "html.parser")
# This will work when you actually upload files
file_upload = base64.b64decode(event["body"])
soup = BeautifulSoup(file_upload, "html.parser")
print(soup)
texts = soup.findAll(text=True)
visible_texts = filter(tag_visible, texts)
full_text = str(u" ".join(t.strip() for t in visible_texts))
return {
"statusCode": 200,
"body": json.dumps(full_text)
}
Additionally in API Gateway - you would need to make the following 2 changes:
Add / in Binary Media Types
Under Method Respone - Add "Content-Type" = "application/html"
I am trying to receive a pdf file by using falcon framework as Backend.
I am a beginner at backend and trying to understand what is happening. So summary, there are 2 classes. one of them, are my friends which are working.
this is the backend side code:
#this is my code
class VehiclePolicyResource(object):
def on_post(self, req, resp, reg):
local_path = create_local_path(req.url, req.content_type)
with open(local_path, 'wb') as temp_file:
body = req.stream.read()
temp_file.write(body)
#this is my friend code
class VehicleOdometerResource(object):
def on_post(self, req, resp, reg):
local_path = create_local_path(req.url, req.content_type)
with open(local_path, 'wb') as temp_file:
body = req.stream.read()
temp_file.write(body)
It is exactly the same and did not give the same answer and I add the route by doing this
api.add_route('/v1/files/{reg}/policies',VehicleResourcesV1.VehiclePolicyResource())
and by using this command in terminal :
HTTP POST localhost:5000/v1/files/SJQ52883Y/policies#/Users/alfreddatui/Autoarmour/aa-atlas/static/asd.pdf
it trying to get the file. But it keep saying, Unsupported media type.
WHILE the other code, receiving image, literally the same code as above, it works.
Any idea ?
Falcon has out of the box support for requests with Content-Type: application/json.
For other content types, you need to provide a media handler for your request.
Here is an attempt at implementing a handler for requests of Content-Type: application/pdf.
import cStringIO
import mimetypes
import uuid
import os
import falcon
from falcon import media
from pdfminer.pdfparser import PDFParser
from pdfminer.pdfdocument import PDFDocument
class Document(object):
def __init__(self, document):
self.document = document
# implement media methods here
class PDFHandler(media.BaseHandler):
def serialize(self, media):
return media._parser.fp.getvalue()
def deserialize(self, raw):
fp = cStringIO.StringIO()
fp.write(raw)
try:
return Document(
PDFDocument(
PDFParser(fp)
)
)
except ValueError as err:
raise errors.HTTPBadRequest(
'Invalid PDF',
'Could not parse PDF body - {0}'.format(err)
)
Update media handlers to support Content-Type: application/pdf.
extra_handlers = {
'application/pdf': PDFHandler(),
}
app = falcon.API()
app.req_options.media_handlers.update(extra_handlers)
app.resp_options.media_handlers.update(extra_handlers)
I got it,
I just notice that Falcon by default will receive JSON file(please correct me if I am wrong)
So I need to make an exception for pdf and image file.
I have around 100 machines running Mersive Solstice, which is a wireless display tool. I'm trying to gather a few important pieces of information, in particular the fulfillment ID for the license for each installed instance.
Using the Solstice OpenControl API, found here, I whipped up a python script to grab everything I needed using a json GET. However, even when using the example GET from the documentation,
import requests
import json
url = ‘http://ip-of-machine/api/stats’
r = requests.get(url)
jsonStats = json.loads(r.text)
usersConnected = jsonStats.m_statistics.m_connectedUsers
I encounter:
Traceback (most recent call last):
File "C:/Python27/test.py", line 7, in <module>
usersConnected = jsonStats.m_statistics.m_connectedUsers
AttributeError: 'dict' object has no attribute 'm_statistics'
Which is very confusing. I've found plenty of similar questions on SO regarding this problem, but not one that's been specifically regarding wrong GET requests from the API Reference guide.
Additionally, here is my script:
import requests
import json
from time import sleep
url = 'test'
f = open("ip.txt", "r")
while(url != ""):
url = f.readline()
url = url.rstrip('\n')
print(url)
try:
r = requests.get(url)
except:
sleep(5)
jsonConfig = json.loads(r.text)
displayName = jsonConfig.m_displayInformation.m_displayName
hostName = jsonConfig.m_displayInformation.m_hostName
ipv4 = jsonConfig.m_displayInformation.m_ipv4
fulfillmentId = jsonConfig.m_licenseCuration.fulfillmentId
r.close()
f.close
I import the URL's from a text document for easy keeping. I'm able to make the connection to the /api/config JSON, and when the URL is put into a browser it does spit out the JSON records:
Json uses "Dicts" which are a type of array. You are just using them in the wrong way. I recommend reading Python Data Structures.
Json.Loads()
Returns a dictionary not a object. Do:
dict['key']['key']
Here is how your code should look:
import requests
import json
from time import sleep
url = 'test'
f = open("ip.txt", "r")
while(url != ""):
url = f.readline()
url = url.rstrip('\n')
print(url)
try:
response = requests.get(url)
json_object = json.loads(response .text)
displayName = json_object['m_displayInformation']['m_displayName']
hostName = json_object['m_displayInformation']['m_hostName']
ipv4 = json_object['m_displayInformation']['m_ipv4']
fulfillmentId = json_object['m_licenseCuration']['fulfillmentId']
except:
pass
response .close()
f.close()
I hope this was helpful!
i found the follwing code in PHP ..
what is the equivalent code in python to do that ?
//At the time of writing it is necessary to enable upload support in the Facebook SDK, you do this with the line:
$facebook->setFileUploadSupport(true);
//Create an album
$album_details = array(
'message'=> 'Album desc',
'name'=> 'Album name'
);
$create_album = $facebook->api('/me/albums', 'post', $album_details);
//Get album ID of the album you've just created
$album_uid = $create_album['id'];
//Upload a photo to album of ID...
$photo_details = array(
'message'=> 'Photo message'
);
$file='app.jpg'; //Example image file
$photo_details['image'] = '#' . realpath($file);
$upload_photo = $facebook->api('/'.$album_uid.'/photos', 'post', $photo_details);
As facebook guys wrote here, they will no longer support python facebook sdk, so it better to make requests via native python tools.
Creating the album:
import urllib,urllib2
access_token = "XXXXXXXXXXXXXXXXXXXXXXXXXXX"
path = "me/albums"
post_args = {'access_token':access_token,'name':"Test Album5", 'message':"Test Album 5"}
post_data = urllib.urlencode(post_args)
file = urllib2.urlopen("https://graph.facebook.com/" + path + "?" , post_data)
response = file.read()
>>>response
'{"id":"XXXXXX702571"}'
Uploading image:
I didn't find a short way to send multipart/form data using urllib2, so I used example from this answer https://stackoverflow.com/a/6843405/592737
import pycurl
import cStringIO
url = 'https://graph.facebook.com/ALBUM_ID/photos'
file ='/path/to/img.jpg'
response = cStringIO.StringIO()
c = pycurl.Curl()
values = [
('file' , (c.FORM_FILE, file)),
('access_token' , access_token),
('message' , 'Image Message'),
]
c.setopt(c.POST, 1)
c.setopt(c.URL,url)
c.setopt(c.HTTPPOST, values)
#c.setopt(c.VERBOSE, 1)
c.setopt(c.WRITEFUNCTION, response.write)
c.perform()
c.close()
>>>response.getvalue()
{"id":"XXXXXX07961"}
But if you're using some fork of facebook python-sdk (like https://github.com/pythonforfacebook/facebook-sdk) you can do it shorter way:
import facebook
access_token = "XXXXXXXXXXXXXXXXXXXXXXXX"
graph = facebook.GraphAPI(access_token)
resp = graph.put_object("me", "albums", name="Test Album",message="Test description")
graph.put_photo(open('/path/to/img.jpg'), 'Look at this cool photo!', resp['id'])
>>> _
{'id': '4394545113756'}
Not supported by Facebook, but you should consider http://code.google.com/p/gae-simpleauth/ for the oauth piece.
Then, as other answers imply, use Python libs like urllib2 to make the graph calls (and possibly simplejson to interpret the responses)